Builders

    Open Source Licence Compliance in Mobile Apps

    A generated dependency inventory listing transitive packages with their SPDX licence identifiers beside an in-app licences screen.

    Nobody reads the licence when adding a dependency. The package solves the problem, the install command works, and the question of what obligations came with it is deferred until a customer's procurement team asks for a software bill of materials, or an acquirer's lawyers do. By then the dependency is load-bearing.

    Short answer

    Open source licences impose obligations, and the obligations vary enormously between them. Permissive licences generally require attribution and preservation of the notice. Copyleft licences add requirements about distributing source and about what happens to code linked with them, which interacts badly with the way mobile apps are distributed. The SPDX licence list is the standard reference identifying each licence unambiguously, and identifying what you have is the first step because most teams cannot answer that question.

    What obligations actually attach

    Attribution is the near-universal one. Most licences require the copyright notice and licence text to be included with the distributed software, which for a mobile app means a licences screen inside the app or an accessible equivalent. Shipping without it is a licence violation for a large share of the dependencies in a typical project.

    Source availability applies to strong copyleft licences. If a licence requires that recipients receive the corresponding source of the work, and your app links that code, the obligation follows the distribution. This is the requirement that makes certain licences a poor fit for a closed-source commercial app.

    Notice of modification is required by several licences when you change the code, which happens more than teams remember: a patched dependency vendored into the repository to fix a bug is a modification.

    Patent grants and their termination clauses appear in several modern licences, and they can affect what happens if you assert a patent against a contributor.

    Restrictions on use appear in licences that are not open source at all despite being distributed like they are, including source-available licences with field-of-use limits. These sit in dependency trees more often than people expect.

    Why mobile distribution complicates it

    The store model changes the analysis in ways that are not obvious.

    Distribution happens through a third party under its own terms, and both Apple's App Review Guidelines and Google Play's policies impose their own conditions on what you distribute. Where a licence's terms conflict with the store's, the conflict has to be resolved rather than ignored, and historically some strong copyleft licences have been treated as incompatible with certain store terms.

    Static linking is the norm. Mobile apps ship as a single artifact with dependencies compiled in, which removes the dynamic-linking distinction that some licence analyses rely on.

    The binary is delivered to users, which means you are distributing, not merely operating a service. Teams used to server-side software sometimes carry over the assumption that internal use does not trigger distribution obligations, and shipping an app is distribution.

    Transitive dependencies are numerous and invisible. A single package can pull in dozens, each with its own licence, and the licence you accepted is the union of all of them rather than the one at the top.

    Building the inventory

    You cannot comply with obligations you cannot enumerate, and the inventory is the part most teams skip.

    Generate it from the build rather than from the manifest. What matters is what shipped, not what was declared, and build tooling on both platforms can produce a dependency list including transitive packages.

    Record the SPDX identifier for each. Licence names in package metadata are inconsistent and sometimes wrong, and the SPDX identifier is the unambiguous form that makes automated checking possible.

    Flag the ones without a clear licence. A dependency with no licence file is not permissively licensed by default; it is unlicensed, which means you have no rights to it beyond what copyright gives you, which is very little.

    Note which dependencies you have modified, since that changes the obligations for several licences.

    Keep it current. An inventory generated once is a snapshot, and the value comes from regenerating it per release so that a new transitive dependency with an unexpected licence is visible when it arrives rather than a year later.

    Meeting the attribution requirement

    This is the obligation almost everyone has and many apps fail, and it is the cheapest to fix.

    Ship a licences screen. Both platforms have conventions for this, usually under settings or about, and there are established tools that generate the content from the dependency inventory automatically.

    Include the full licence text, not a list of names. Most licences require the text itself to accompany the distribution, and a list saying which libraries were used does not satisfy that.

    Keep it generated rather than hand-maintained. A hand-written attribution screen is out of date after the next dependency change, and a generated one is correct by construction.

    Make it reachable without an account. Attribution that sits behind a login is not accessible to everyone who received the software.

    What to do about a problematic licence

    Occasionally the inventory surfaces something incompatible with how you distribute, and the options are finite.

    Replace the dependency. Usually the cleanest answer, and easier the earlier you find it, which is the practical argument for generating the inventory before a dependency becomes structural.

    Isolate it. Some obligations attach differently depending on how code is combined, and there may be an architecture where the dependency runs as a separate component. This is a genuine legal question rather than an engineering preference, and it is where you want advice rather than a forum answer.

    Comply with the obligation. If the requirement is to make corresponding source available and you can do that, it may simply be acceptable, and a number of commercial apps do exactly this.

    Obtain a different licence. Many projects offer commercial licensing alongside an open one, and for a dependency you genuinely need this is often the fastest resolution.

    What is not a strategy is hoping. Licence obligations do not expire because nobody noticed, and the moment they surface is usually a due-diligence process where the cost of the problem is highest.

    Where this connects to security

    The same inventory answers a different question, which is why the effort is worth more than compliance alone.

    Knowing every dependency in a shipped build is the prerequisite for knowing whether any of them has a known vulnerability, and it is the same list. Teams that build a licence inventory get a vulnerability inventory almost free.

    It also surfaces dependencies nobody remembers adding, which is a recurring finding on mobile projects and a reasonable prompt to remove code that is no longer used.

    An automated pass over the built artifact such as PTKD.com is a practical way to see what actually shipped, including SDKs and libraries present in the binary that a package manifest may not reflect. Android's security best practices and the OWASP MASVS both assume you can enumerate your dependencies, and that assumption is the one most often unmet.

    A note on scope: everything here is engineering practice for making obligations visible and manageable. Whether a specific licence combination is acceptable for your product is a legal question, and the point of the inventory is to let a lawyer answer it in an hour rather than a month.

    The questions you will eventually be asked

    Compliance work feels abstract until someone external asks, and knowing the questions in advance makes the preparation concrete.

    Can you provide a software bill of materials? This arrives from enterprise customers and increasingly from public sector buyers. A generated inventory answers it in minutes; without one it becomes a week of archaeology.

    Which of your dependencies are copyleft, and how are they combined? This is a due-diligence question and it is asked because the answer occasionally changes a valuation. Having it documented, with the reasoning reviewed once by someone qualified, is a much better position than assembling it under deadline.

    Do you have the right to distribute all of the code in your product? A dependency with no licence file makes this answer no, strictly speaking, and finding one during diligence is worse than finding it now.

    How do you satisfy attribution requirements? Pointing at an in-app licences screen ends the conversation. Explaining that you intend to build one does not.

    What is your process when a dependency is added? The answer they want is that licence identification happens at the point of addition, automatically, rather than as a periodic clean-up.

    Making it a process rather than a project

    The reason licence work is painful is that it gets done as a one-off audit and then decays immediately.

    Put the inventory generation into the build, so it produces an artifact for every release and drift is visible.

    Add an allowed-licence list and fail the build on anything outside it. This sounds heavy-handed and it is the single most effective control, because it moves the decision to the moment the dependency is added, when replacing it is cheap.

    Keep a short exceptions file with a reason and an owner for each. Exceptions are legitimate; undocumented exceptions are how a policy stops meaning anything.

    Regenerate the attribution screen as part of the same step, so it cannot fall out of date without the build noticing.

    That is perhaps a day of setup, and it converts a recurring audit into something that happens automatically and produces evidence.

    Licences that are not what they look like

    Two categories cause disproportionate trouble because they resemble ordinary open source and are not.

    Source-available licences permit reading and modifying the code while restricting use, often forbidding competing commercial offerings or requiring a licence above a revenue threshold. Several widely used packages have moved to these terms in recent years, usually at a major version, which means an ordinary dependency upgrade can change your obligations without any signal in the changelog you read.

    Dual-licensed projects offer a copyleft licence and a commercial one. Using the copyleft version is fine if you can meet its terms and is frequently not what a closed-source product wants, and the commercial option exists precisely for that case.

    The practical defence for both is that licence identification runs on every dependency change, including upgrades, rather than only on new additions. A version bump that changes a licence is invisible to a process that only checks packages the first time it sees them.

    A table of what each obligation usually requires

    ObligationTypically triggered byWhat shipping it means
    AttributionAlmost every licenceLicences screen with full text
    Notice of modificationSeveral permissive and copyleft licencesRecord what you changed
    Corresponding sourceStrong copyleftProvide source to recipients
    Patent termsSeveral modern licencesUnderstand termination clauses
    Use restrictionsSource-available licencesCheck field-of-use limits

    The table is deliberately general, because the exact trigger depends on the specific licence text and on how the code is combined. Its purpose is to show that the obligations are few in number and different in kind, which makes the inventory the useful artifact rather than a licence-by-licence reading exercise.

    What to take away

    Most dependencies carry obligations, and attribution is the near-universal one that most apps do not meet.

    Generate the dependency inventory from the build rather than the manifest, record SPDX identifiers, and regenerate per release.

    Mobile distribution is distribution, static linking is the norm, and store terms add their own conditions, so server-side licence intuitions do not transfer.

    Ship a generated licences screen containing full licence text, reachable without an account, and regenerate it in the same build step that produces the inventory so it cannot silently fall out of date.

    And treat the inventory as dual purpose, because the list that answers the licence question is the same list that answers the vulnerability question.

    Run licence identification on upgrades as well as additions, since a package can change its terms at a major version without any signal in the changelog you actually read.

    • #open source
    • #licensing
    • #dependencies
    • #sbom
    • #compliance
    • #spdx

    Frequently asked questions

    What obligations come with open source dependencies?
    Attribution is the near-universal one: most licences require the copyright notice and licence text to accompany the distributed software, which for a mobile app means an in-app licences screen. Copyleft licences add requirements about making corresponding source available. Several licences require notice when you modify the code, which includes vendoring a patched dependency into your repository.
    Does shipping an app count as distribution?
    Yes. The binary is delivered to users, which is distribution rather than internal use or operating a service. Teams used to server-side software sometimes carry over the assumption that obligations only attach on distribution and that they are not distributing, which does not hold for a mobile app. Static linking is also the norm, removing a distinction some licence analyses rely on.
    How do I build a dependency inventory?
    Generate it from the build rather than from the manifest, since what matters is what shipped including transitive packages. Record the SPDX identifier for each, because licence names in package metadata are inconsistent and sometimes wrong. Flag dependencies with no licence file, which are unlicensed rather than permissive, and note which ones you have modified.
    What does a compliant attribution screen look like?
    It contains the full licence text rather than a list of library names, because most licences require the text itself to accompany the distribution. It should be generated from the dependency inventory rather than hand-maintained, so it stays correct after dependency changes, and it should be reachable without an account since attribution is owed to everyone who received the software.
    What if a dependency has an incompatible licence?
    The options are replacing it, isolating it architecturally where the obligations attach differently, complying with the requirement if you can, or obtaining a commercial licence from a project that offers one. Which applies is a legal question rather than an engineering preference. What does not work is waiting, since obligations surface during due diligence when the cost is highest.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free