bitracker
Necromancy 101: Reanimating Stash 3.11 with Bytecode and Prayers

april 24, 2026 // 2 min read

hey again!! :33 so, i decided to spin up an old instance of Atlassian Stash (now known as Bitbucket Server). why? because this

the license boss-fight

first problem: Stash 3.11 uses the V2 license decoder. its a jar called atlassian-extras-decoder-v2-3.2.jar. it expects a signed payload. i wrote a python script to mimic the structure: [Length][Zlib_Props][Signature].

but theres a catch. the Signature.verify() method in java is very picky... if you send it a random "dummy" string as a signature, it screams SignatureException: invalid encoding because its not a valid ASN.1 DER sequence.

some bytecode patching

instead of actually trying to forge a DSA signature (who has time for that?), i just patched the bytecode.

i found the call to verify() and replaced it with a goto.

// Version2LicenseDecoder.class
        L: 
            line 185
            goto N // just jump to success

        // skipping this part
        M: 
            line 187
            new com/atlassian/extras/common/LicenseException
            dup
            ldc "Failed to verify the license."
            invokespecial com/atlassian/extras/common/LicenseException.<init> (Ljava/lang/String;)V
            athrow 
        N: 
            line 203
            goto U

        // some blahblah

        U: 
            // try-end:     range=[A-U] handler=V:java/io/IOException 
            line 209
            goto X

        X: 
            line 211
            aload licenseText // profit!
            areturn

and boom. it doesnt even try to verify anymore. it just assumes im a legitimate paying customer.

the "expired" trap

even after the patch, the app kept crying: Your license has expired. turns out, Atlassian is obsessed with casing and namespaces

  • ContactEmail? WRONG. it MUST be ContactEMail (capital M)
  • MaintenanceExpiryDate? not enough. you need stash.MaintenanceExpiryDate too

once i fixed the python generator to include every possible variation of the date and fixed the casing, the server finally accepted my "real" license

when the database is too new

next boss: PostgreSQL 9.6

Stash 3.11 comes with a JDBC driver from 2015 (postgresql-9.4) when i tried to push code, the Branch Permissions plugin crashed the whole request why? because the old driver tries to query am.amcanorder from the system catalogs. but Postgres 9.6+(??) deleted that column... so i just downgraded pgsql to 9.4

some conclusions

so right now navi is running:

  • Oracle JDK 1.7 (yikes)
  • Stash 3.11 (patched to hell) (- ./sillylib/atlassian-extras-decoder-v2-3.2.jar:/opt/atlassian/stash/atlassian-stash/WEB-INF/lib/atlassian-extras-decoder-v2-3.2.jar)
  • PostgreSQL 9.4

unlimited