Skip to main content

Release-gate linter that checks Luciq-SDK apps for PII-masking gaps (iOS + Android).

Project description

Luciq PII Masking Linter

Catches unmasked PII — card numbers, SSNs, emails, passwords — in your Luciq-SDK app before it ships, across screenshots, Session Replay, and network logs. Use it in your editor, in CI, or as a release gate.

Works for iOS (Swift) and Android (Kotlin/Java).

Install for: Android · iOS — each covers local + CI.


Install

Android

Native Android Lint, distributed via JitPack — no Python needed.

1. Add JitPack to settings.gradle.kts:

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://jitpack.io") }   // ← add this
    }
}

2. Add the check to app/build.gradle.kts:

dependencies {
    lintChecks("com.github.luciqai:luciq-masking-lint:0.2.0")
}

3. Run it:

./gradlew :app:lint

Unmasked PII is now a red Lint error — a squiggle in Android Studio as you type, and a failed build in CI. It reads your project's luciq.yml (compliance level + custom keywords) — the same file the CLI uses. Control blocking vs. report-only in Lint settings.

On Maven Central instead? Use ai.luciq:luciq-masking-lint:0.2.0 and drop the JitPack line.

iOS

Install the command-line tool (Python 3.8+, no other dependencies). Use pipx so the command lands in ~/.local/bin — a stable location the Xcode build can find:

pipx install luciq-masking-linter

To see findings inline in Xcode, add a Run Script build phase. Xcode build phases run with a minimal PATH, so add ~/.local/bin before calling the command — otherwise the build reports it as "not installed" even when it is:

export PATH="$HOME/.local/bin:$PATH"
luciq-masking-linter "$SRCROOT" --format xcode --mode warn

CI / other

Install the tool, then run it where you want a gate. GitHub Actions:

- uses: actions/setup-python@v5
- run: pip install luciq-masking-linter
- run: luciq-masking-linter . --mode enforce      # fails the job on a gap

Any CI works the same: install, then luciq-masking-linter . --mode enforce.

  • Inline PR annotations: --format github · GitHub Code Scanning: --format sarif.
  • Android CI can skip Python and just run ./gradlew :app:lint.

Tuning the linter

How you control the linter — blocking vs. report-only, output format, what to skip — depends on your platform, but the goal is the same. Jump to yours:

Compliance level and exclude always come from luciq.yml — shared by both platforms.

iOS / CI — command-line flags

The luciq-masking-linter command takes a path to scan plus a few flags.

luciq-masking-linter [path] --mode enforce --compliance gdpr --format sarif
Flag Default What it does
--mode warn warn reports and exits 0; enforce exits 1 on a blocking gap (the gate)
--compliance from luciq.yml none / soc2 / pci / gdpr / hipaa — overrides the file
--format text text, xcode (inline in Xcode), github (PR annotations), sarif (Code Scanning)
--exclude a path or glob to skip (repeatable)

A run looks like:

[FAIL] unmasked-field PaymentView.swift:24 — card field is not masked …
[warn] unmasked-field ProfileView.swift:31 — phone field is not masked …
Summary: 1 fail, 1 warn   →   BLOCK release

Android — Lint settings

Configure the check in app/build.gradle.kts, under android { lint { … } }.

Setting Default What it does
abortOnError = false true report only, never fail the build (like --mode warn)
warning += "LuciqUnmaskedPii" demote just this check to a non-blocking warning
warningsAsErrors = true false make even advisory warnings block
baseline = file("lint-baseline.xml") accept existing findings; block only new ones
sarifReport = true write a SARIF report (for GitHub Code Scanning)

The check reports under four issue ids — name any of them in warning += / disable +=: LuciqUnmaskedPii (unmasked field) and LuciqMaskingConfig (project posture: auto-mask, network, FLAG_SECURE, consent, old SDK) are errors that block; LuciqUnmaskedPiiAdvisory and LuciqMaskingConfigAdvisory are non-blocking warnings.

Compliance level can also be set with the LUCIQ_COMPLIANCE env var. To switch warn/enforce per run, gate abortOnError on a property:

android { lint { abortOnError = !project.hasProperty("luciqWarn") } }

./gradlew :app:lint enforces · ./gradlew :app:lint -PluciqWarn warns.


Skip a finding

If a flagged field isn't really PII, skip it with a comment:

  • // luciq-mask-ignore on the field's line (or the line just above it).
  • // luciq-mask-ignore-file anywhere in a file to skip that whole file.
  • Add a reason for the audit trail: // luciq-mask-ignore: masked upstream.

Card fields can't be skipped under pci.


Configure — luciq.yml (optional)

Put one file at your project root. It holds the handful of things the linter can't read from your code. Both the CLI and the Android Lint check read it.

pii_masking:
  compliance: gdpr               # none | soc2 | pci | gdpr | hipaa
  keywords:                      # your app-specific PII field names
    account: [loyaltyId, membershipNo]
  exclude: [app/generated]       # paths to skip

Compliance levels — what blocks vs. warns

Level Blocks on
none / soc2 card, SSN, credentials
pci same, and card waivers are refused
gdpr + email, phone, name, address, DOB, every text input; consent required
hipaa all of the above + health; MEDIA auto-mask + consent required

Exit codes

0 = clean, or --mode warn. 1 = --mode enforce and a blocking gap.

On Android, ./gradlew :app:lint fails the build on a blocking gap the same way — unless abortOnError = false.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

luciq_masking_linter-0.2.0.tar.gz (17.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

luciq_masking_linter-0.2.0-py3-none-any.whl (14.4 kB view details)

Uploaded Python 3

File details

Details for the file luciq_masking_linter-0.2.0.tar.gz.

File metadata

  • Download URL: luciq_masking_linter-0.2.0.tar.gz
  • Upload date:
  • Size: 17.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for luciq_masking_linter-0.2.0.tar.gz
Algorithm Hash digest
SHA256 8495b2c39145f44f38cd8ff2f2795a60e216844fa7bf33cd1a8dc6390fb43b54
MD5 eb96ab6cd85ae8294f42febf67731178
BLAKE2b-256 a2c11b3baa68d046c507ae18dda812dab74ba91993badbca5cc008e20b9058f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for luciq_masking_linter-0.2.0.tar.gz:

Publisher: release-pypi.yml on luciqai/luciq-masking-linter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file luciq_masking_linter-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for luciq_masking_linter-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e08152d9c60daf1783f6f66436987a1148bc17791c35f9a6ccd996cbca5e3071
MD5 f9b3852305bd816b3e606354f3970549
BLAKE2b-256 d6a8eab24c8bcd7bb7241682734bc1a7de2c9739c7b486f4812d2bd29938e14b

See more details on using hashes here.

Provenance

The following attestation bundles were made for luciq_masking_linter-0.2.0-py3-none-any.whl:

Publisher: release-pypi.yml on luciqai/luciq-masking-linter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page