Handle Non-RPM Software

inspectah detects pip, npm, and gem packages alongside unmanaged files that live outside the RPM package manager. This guide covers how the detection works, what ends up in the Containerfile, and how to adjust the results.

Language packages (Tier 1)

Language packages are detected automatically during every scan. No extra flags required.

What gets detected

Ecosystem Detection method What inspectah looks for
pip Virtual environments pyvenv.cfg files under /opt, /srv, /usr/local
pip System packages pip list --format=json, filtered against RPM-owned packages
npm Lockfile projects package-lock.json files under scan roots
npm Manifest-only projects package.json when no lockfile is present
gem Lockfile projects Gemfile.lock files under scan roots
gem System gems gem list --local, filtered against RPM-owned gems

Confidence levels

Each detected environment gets a confidence level that controls how it renders in the Containerfile:

Level Meaning Containerfile rendering
High Lockfile or requirements.txt present; full dependency list Active RUN directives
Medium Packages detected via dist-info or runtime command; list may be incomplete Commented-out directives (# RUN ...)
Low Manifest-only (e.g., package.json without lockfile); no pinned versions Advisory comment only

High-confidence items run out of the box. Medium-confidence items need you to uncomment them after verifying the package list. Low-confidence items are informational only – you write the install commands yourself.

Containerfile output

For a high-confidence pip venv at /opt/myapp/venv:

# --- pip packages: /opt/myapp/venv (from requirements.txt) ---
COPY language-packages/pip/opt-myapp-venv/requirements.txt /tmp/myapp-venv-requirements.txt
RUN python3 -m venv /opt/myapp/venv \
    && /opt/myapp/venv/bin/pip install -r /tmp/myapp-venv-requirements.txt \
    && rm /tmp/myapp-venv-requirements.txt

For a medium-confidence pip venv (no requirements.txt):

# pip packages: /opt/myapp/venv (detected via dist-info — transitive deps may differ)
# Uncomment after verifying package list is complete:
# RUN python3 -m venv /opt/myapp/venv \
#     && /opt/myapp/venv/bin/pip install flask==2.3.3 requests==2.31.0

npm and gem environments follow the same pattern with their respective install commands (npm ci, bundle install).

Runtime prerequisites

The Containerfile emits a warning if a required runtime package (python3, nodejs, rubygems) is not present in the RPM package list. If you see this warning, add the runtime package to your Containerfile before the language package section.

Reviewing in refine

The refine UI shows a Language Packages section with each detected environment. You can:

  • Toggle individual environments between included and excluded
  • View the detected packages and their versions
  • See the confidence level and detection method

Manifest files (requirements.txt, package-lock.json, Gemfile.lock) are bundled in the tarball under language-packages/ and subject to redaction (auth-bearing URLs are scrubbed).

Unmanaged files (Tier 2)

Unmanaged file scanning is opt-in. Pass --include-unmanaged to enable it:

sudo inspectah scan --include-unmanaged

What gets scanned

inspectah catalogs files under /opt, /srv, and /usr/local that are not owned by an RPM package and not already claimed by a Tier 1 language package environment.

Before bundling, inspectah shows the total size and prompts for confirmation. Suppress the prompt with -y/--yes for CI use:

sudo inspectah -y scan --include-unmanaged

Excluding paths

Use --exclude-path (repeatable) to skip directories you do not want bundled:

sudo inspectah scan --include-unmanaged \
    --exclude-path /opt/backups \
    --exclude-path /srv/archive

Provenance signals

Each unmanaged file carries provenance signals to help you decide whether to include it:

Signal What it tells you
Last modified When the file was last changed
Permissions File permission bits
UID / GID Owning user and group
Writable mount Whether the file sits on a writable filesystem
Mutable Whether the path is on a mutable filesystem layer
Service working dir Whether a systemd service uses this path as its working directory

Containerfile output

Regular files render as COPY directives:

# === Unmanaged files (no package manager provenance) ===
# /opt/myapp/
COPY unmanaged/opt/myapp/config.yml /opt/myapp/config.yml
COPY unmanaged/opt/myapp/app.jar /opt/myapp/app.jar

Symlinks render as RUN ln -sf directives instead of COPY:

RUN ln -sf '/opt/myapp/current' '/opt/myapp/latest'

Reviewing in refine

The refine UI shows an Unmanaged Files section where you can toggle individual files. Provenance signals are displayed in the detail pane to help you decide which files to carry forward.

Aggregate mode

In aggregate scans, both language_packages and unmanaged_files appear as aggregate sections with the same prevalence-zone grouping (Consensus, Near Consensus, Divergent) used by other sections.