Add DEVELOPMENT.md and SECURITY.md
This commit is contained in:
+236
@@ -0,0 +1,236 @@
|
||||
# chguard Threat Model and Security Scope
|
||||
|
||||
chguard is a command-line systems administration tool. It is designed to be
|
||||
executed intentionally by an operator, sometimes with elevated privileges, to
|
||||
snapshot and restore filesystem ownership and permission metadata.
|
||||
|
||||
Because of that design, chguard's security model is different from that of a
|
||||
network service, web application, daemon, sandbox, or setuid program. chguard
|
||||
does not attempt to defend against arbitrary local compromise of the account
|
||||
executing it. If an attacker can control the command line, environment, working
|
||||
directory, `PATH`, selected database, installed Python package, or wrapped
|
||||
system command used by the operator, they may be able to influence what chguard
|
||||
does. That situation is considered a local trust-boundary failure outside
|
||||
chguard's intended security model.
|
||||
|
||||
chguard only manages filesystem metadata. It does not read, store, compare,
|
||||
restore, or protect file contents.
|
||||
|
||||
## Core Assumptions
|
||||
|
||||
chguard assumes that the person running the tool understands what they are
|
||||
asking it to do.
|
||||
|
||||
In particular:
|
||||
|
||||
* If chguard is run as root, the root user is assumed to control and understand
|
||||
the command line, environment, database path, restore root, and wrapped
|
||||
command being used.
|
||||
* If `--db` is used, the selected SQLite database path and its contents are
|
||||
assumed to be trusted local administrative state chosen by the operator.
|
||||
* If `--root` is used during restore, the alternate restore root is assumed to
|
||||
be intentionally selected by the operator.
|
||||
* If `--yes` is used, the operator is intentionally bypassing the interactive
|
||||
confirmation prompt.
|
||||
* Wrapper mode commands are assumed to be the trusted `chown`, `chmod`, or
|
||||
`chgrp` implementation that the operator intended to execute.
|
||||
* The operator is expected to understand the impact of restoring ownership and
|
||||
permission bits, especially when restoring as root.
|
||||
|
||||
## What chguard Records
|
||||
|
||||
chguard snapshots a narrow set of filesystem metadata:
|
||||
|
||||
* Relative path under the snapshot root.
|
||||
* Entry type: regular file, directory, or symbolic link.
|
||||
* Permission bits.
|
||||
* Numeric `uid`.
|
||||
* Numeric `gid`.
|
||||
|
||||
chguard deliberately does not snapshot:
|
||||
|
||||
* File contents.
|
||||
* File hashes.
|
||||
* ACLs.
|
||||
* Extended attributes.
|
||||
* Capabilities.
|
||||
* SELinux, AppArmor, or other MAC labels.
|
||||
* Deleted files.
|
||||
* Newly created files.
|
||||
* Device nodes, sockets, FIFOs, or other special files.
|
||||
|
||||
User and group names are display-only. Numeric `uid` and `gid` values are the
|
||||
source of truth.
|
||||
|
||||
## What Is In Scope
|
||||
|
||||
chguard tries to protect careful administrators from common and serious mistakes
|
||||
that can occur when a privileged CLI tool records and restores filesystem
|
||||
metadata.
|
||||
|
||||
In-scope security concerns include:
|
||||
|
||||
* Restore must not create, delete, move, rename, or rewrite files.
|
||||
* Restore must not change file contents.
|
||||
* Restore must preview applicable owner and mode changes before applying them.
|
||||
* Mutating restore must require confirmation unless `--yes` is provided.
|
||||
* Mutating prune operations must require confirmation unless `--yes` is
|
||||
provided.
|
||||
* Preview and dry-run restore should remain usable without root.
|
||||
* chguard must not automatically run sudo or otherwise escalate privileges.
|
||||
* Scanning and restoring should use no-follow filesystem operations and avoid
|
||||
following symlink targets.
|
||||
* Restore should re-check current filesystem state before applying chmod or
|
||||
chown operations.
|
||||
* Restore should skip missing paths, unsupported file types, and type mismatches
|
||||
rather than replacing them.
|
||||
* Wrapper mode should stay limited to ownership and permission commands:
|
||||
`chown`, `chmod`, and `chgrp`.
|
||||
* Wrapper mode should not use a shell to execute the wrapped command.
|
||||
* SQLite access should use parameterized queries for operator-provided names and
|
||||
paths.
|
||||
* A state created by chguard through normal scanning should not contain relative
|
||||
paths that escape the snapshot root.
|
||||
|
||||
These measures are defense-in-depth. They are intended to reduce the chance of
|
||||
accidental metadata changes, symlink traversal, unintended privilege changes, or
|
||||
unsafe restore behavior when chguard is used normally by an administrator.
|
||||
|
||||
## What Is Out Of Scope
|
||||
|
||||
The following are generally out of scope and should not be reported as chguard
|
||||
vulnerabilities unless they also bypass one of chguard's explicit hardening
|
||||
mechanisms:
|
||||
|
||||
* A malicious local user who can already control the root user's command line,
|
||||
shell environment, working directory, `PATH`, Python environment, installed
|
||||
package, or invoked binaries.
|
||||
* A root user intentionally selecting a malicious or manually edited SQLite
|
||||
database with `--db`.
|
||||
* A root user intentionally restoring a snapshot that sets unsafe ownership or
|
||||
permissions.
|
||||
* A root user intentionally using `--root` to apply a trusted snapshot under a
|
||||
different filesystem tree.
|
||||
* A root user intentionally passing `--yes` and bypassing confirmation.
|
||||
* A user intentionally wrapping a malicious binary whose basename is `chown`,
|
||||
`chmod`, or `chgrp`.
|
||||
* A user relying on chguard to restore file contents, deleted files, ACLs,
|
||||
extended attributes, capabilities, MAC labels, or full undo semantics.
|
||||
* A user relying on chguard as a sandbox for untrusted local users or untrusted
|
||||
command execution.
|
||||
* A compromised system where an attacker already controls root-owned files,
|
||||
root's shell, root's Python packages, root's environment, or the privileged
|
||||
tools chguard invokes.
|
||||
* Reports that amount to "if root runs this tool with malicious options, root
|
||||
can make the system do dangerous things."
|
||||
|
||||
chguard is a tool for administrators, not a sandbox for hostile local users. It
|
||||
cannot make unsafe local trust decisions safe if the operator's own execution
|
||||
environment is already attacker-controlled.
|
||||
|
||||
## Trusted Snapshot Databases
|
||||
|
||||
chguard snapshots are stored in a local SQLite database. By default, chguard uses
|
||||
the platform-specific user data directory for the invoking account. Operators
|
||||
may override this with `--db`.
|
||||
|
||||
Snapshot databases should be treated as trusted administrative state. They can
|
||||
contain filesystem paths, ownership, group, permission, timestamp, and snapshot
|
||||
root information. They do not contain file contents, but the metadata can still
|
||||
reveal operational details about a system.
|
||||
|
||||
Before running restore, especially as root or with `--yes`, the operator should
|
||||
be confident that the selected database is the intended one and has not been
|
||||
tampered with.
|
||||
|
||||
chguard-created snapshots are expected to contain paths relative to the snapshot
|
||||
root. chguard does not treat an arbitrary attacker-supplied SQLite database as
|
||||
untrusted input to be safely enforced.
|
||||
|
||||
## Wrapper Mode
|
||||
|
||||
Wrapper mode exists to take an automatic pre-command snapshot before running a
|
||||
metadata-changing command:
|
||||
|
||||
```bash
|
||||
chguard -- chmod 755 path
|
||||
chguard -- chown user:group path
|
||||
chguard -- chgrp group path
|
||||
```
|
||||
|
||||
Wrapper mode is intentionally limited to `chmod`, `chown`, and `chgrp` by command
|
||||
basename. chguard snapshots existing non-option path arguments that it can
|
||||
identify, then runs the wrapped command and returns that command's exit code.
|
||||
|
||||
Wrapper mode is not a full parser for every possible option accepted by those
|
||||
commands. It is a guardrail for common ownership and permission changes, not a
|
||||
general command supervision framework.
|
||||
|
||||
## Symlinks And Filesystem Races
|
||||
|
||||
chguard uses `lstat()` and no-follow operations while scanning and restoring. It
|
||||
records symbolic link entries and attempts no-follow ownership or permission
|
||||
restoration where the platform supports it. It should not follow a symbolic link
|
||||
target and apply changes to the target as part of scanning or restore.
|
||||
|
||||
Restore is best-effort across platforms. Some operations, such as changing
|
||||
symlink permissions, are not supported everywhere and may be skipped.
|
||||
|
||||
Because chguard operates on a live filesystem, concurrent filesystem changes can
|
||||
still affect what exists at the moment restore runs. chguard mitigates this by
|
||||
re-checking paths before applying changes and by skipping missing paths, special
|
||||
files, and type mismatches. It does not claim to provide a transactional
|
||||
filesystem restore.
|
||||
|
||||
## Local Compromise
|
||||
|
||||
chguard includes hardening against some local filesystem attack patterns because
|
||||
it is often run with high privileges. For example, it avoids symlink traversal,
|
||||
does not use a shell for wrapper mode, previews restore changes, and does not
|
||||
automatically escalate privileges.
|
||||
|
||||
However, local compromise cannot be ruled out completely for a privileged CLI
|
||||
tool. If an attacker can influence the administrator's shell, environment,
|
||||
database, binaries, Python packages, current working directory, or command-line
|
||||
arguments, they may be able to influence chguard's behavior.
|
||||
|
||||
Such scenarios are treated as local compromise or operator trust failures, not
|
||||
as vulnerabilities in chguard by themselves.
|
||||
|
||||
## Security Report Guidance
|
||||
|
||||
Useful vulnerability reports include issues where chguard behaves unsafely
|
||||
despite the documented trust model. Examples include:
|
||||
|
||||
* chguard follows a symlink target during save or restore in a way that causes
|
||||
unintended privileged chmod or chown operations.
|
||||
* Restore creates, deletes, moves, renames, or rewrites files.
|
||||
* Restore applies owner or mode changes without previewing them first.
|
||||
* Restore applies changes without confirmation when `--yes` was not provided.
|
||||
* Dry-run or preview applies filesystem changes.
|
||||
* chguard automatically escalates privileges or invokes sudo.
|
||||
* A snapshot produced by normal chguard scanning can contain paths that escape
|
||||
the snapshot root during restore.
|
||||
* Wrapper mode accepts and executes unsupported command classes outside `chown`,
|
||||
`chmod`, or `chgrp`.
|
||||
* Wrapper mode introduces shell injection when running ordinary operator-provided
|
||||
path names or arguments.
|
||||
* SQLite operations allow operator-provided state names or paths to alter
|
||||
unintended database rows through injection.
|
||||
* A failed safety check is silently ignored and chguard proceeds with a dangerous
|
||||
operation anyway.
|
||||
|
||||
Less useful reports, and normally out of scope, include:
|
||||
|
||||
* "Root can restore dangerous permissions."
|
||||
* "Root can pass `--yes` and bypass the confirmation prompt."
|
||||
* "Root can point `--db` at a malicious SQLite database."
|
||||
* "Root can use `--root` to restore metadata into a different tree."
|
||||
* "A malicious local user can compromise chguard after already controlling
|
||||
root's environment, Python packages, or binaries."
|
||||
* "chguard does not restore file contents, ACLs, xattrs, capabilities, or full
|
||||
deleted-file state."
|
||||
|
||||
Reports about concrete bypasses of chguard's hardening are welcome. The project
|
||||
does not treat intentional administrator-controlled execution as a vulnerability
|
||||
by itself.
|
||||
Reference in New Issue
Block a user