Added first-class **Postman** scanning target: new kingfisher scan postman subcommand (and equivalent --postman-* flags) fetches workspaces, collections, and environments via the Postman API and scans them for hard-coded credentials in request auth blocks, pre-request/test scripts, saved example responses, and — notably — secret-typed environment variables, which the API returns in plaintext despite the UI mask. Selectors: --workspace, --collection, --environment, --all, with optional --include-mocks-monitors and --api-url for self-hosted endpoints. Authenticates via KF_POSTMAN_TOKEN (or POSTMAN_API_KEY) sent as X-Api-Key; honors X-RateLimit-RetryAfter on 429s. Findings link back to https://go.postman.co/... URLs in reports.

This commit is contained in:
Mick Grove 2026-04-29 11:09:47 -07:00
commit c387ac08d2
10 changed files with 303 additions and 539 deletions

View file

@ -132,7 +132,7 @@ jobs:
toolchain: ${{ env.RUST_TOOLCHAIN }}
- name: Set up MSYS2
uses: msys2/setup-msys2@cafece8e6baf9247cf9b1bf95097b0b983cc558d # v2.31.0
uses: msys2/setup-msys2@e9898307ac31d1a803454791be09ab9973336e1c # v2.31.1
with:
msystem: ${{ matrix.msystem }}
update: true

View file

@ -25,7 +25,7 @@ jobs:
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
@ -46,7 +46,7 @@ jobs:
CI: true
- name: Upload artifact
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: docs-site/site

View file

@ -141,7 +141,7 @@ jobs:
--plat-name win_arm64
- name: Publish to PyPI (Trusted Publishing)
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1
with:
packages-dir: dist-pypi
verbose: true

View file

@ -274,7 +274,7 @@ jobs:
toolchain: ${{ env.RUST_TOOLCHAIN }}
- name: Set up MSYS2
uses: msys2/setup-msys2@cafece8e6baf9247cf9b1bf95097b0b983cc558d # v2.31.0
uses: msys2/setup-msys2@e9898307ac31d1a803454791be09ab9973336e1c # v2.31.1
with:
msystem: ${{ matrix.msystem }}
update: true

798
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -94,10 +94,10 @@ clap = { version = "4.5", features = [
anyhow = "1.0"
bstr = { version = "1.12", features = ["serde"] }
fixedbitset = "0.5"
gix = { version = "0.81", features = ["max-performance-safe", "serde", "blocking-network-client"] }
gix = { version = "0.83", features = ["max-performance-safe", "serde", "blocking-network-client"] }
ignore = "0.4"
petgraph = "0.8"
roaring = "0.11.3"
roaring = "0.11.4"
schemars = "0.8"
serde = { version = "1.0", features = ["derive", "rc"] }
smallvec = { version = "1", features = [
@ -168,13 +168,13 @@ tree_magic_mini = "3.2"
content_inspector = "0.2.4"
rustc-hash = "2.1.1"
bzip2-rs = "0.1.2"
zip = { version = "8.5.0", default-features = false, features = ["deflate", "deflate64", "time"] }
zip = { version = "8.6.0", default-features = false, features = ["deflate", "deflate64", "time"] }
tar = "0.4.44"
lzma-rs = "0.3.0"
asar = "0.3.0"
cfb = "0.14"
rusqlite = { version = "0.39", features = ["bundled"] }
blake3 = "1.8.2"
blake3 = "1.8.5"
memchr = "2.7"
memmap2 = "0.9.9"
futures = "0.3.31"
@ -195,7 +195,7 @@ mimalloc = { version = "0.1.48", features = ["override"] }
thread_local = "1.1.9"
bloomfilter = "3.0.1"
uuid = "1.19.0"
rand = "0.10.0"
rand = "0.10.1"
percent-encoding = "2.3.2"
self_update = { version = "0.44.0", default-features = false, features = ["reqwest", "rustls", "archive-tar", "archive-zip", "compression-flate2"] }
semver = "1.0.27"
@ -209,7 +209,7 @@ aws-sdk-iam = { version = "1.104.0", default-features = false, features = ["defa
aws-sdk-ec2 = { version = "1.211.0", default-features = false, features = ["default-https-client", "rt-tokio"] }
aws-sdk-dynamodb = { version = "1.105.0", default-features = false, features = ["default-https-client", "rt-tokio"] }
aws-sdk-lambda = { version = "1.116.0", default-features = false, features = ["default-https-client", "rt-tokio"] }
aws-sdk-kms = { version = "1.100.0", default-features = false, features = ["default-https-client", "rt-tokio"] }
aws-sdk-kms = { version = "1.106.0", default-features = false, features = ["default-https-client", "rt-tokio"] }
aws-sdk-secretsmanager = { version = "1.100.0", default-features = false, features = ["default-https-client", "rt-tokio"] }
aws-sdk-sqs = { version = "1.90.0", default-features = false, features = ["default-https-client", "rt-tokio"] }
aws-sdk-sns = { version = "1.89.0", default-features = false, features = ["default-https-client", "rt-tokio"] }

View file

@ -38,7 +38,7 @@ bstr.workspace = true
memchr = "2.7"
# Git types (minimal, for ObjectId and Time)
gix = { version = "0.81", default-features = false, features = ["serde", "sha1"] }
gix = { version = "0.83", default-features = false, features = ["serde", "sha1"] }
# Console formatting
console = "0.16"

View file

@ -27,7 +27,7 @@ rules:
(?x)
\b
(
(?:sk|rk)_(?:test|live)_[A-Za-z0-9]{24,128}
(?:sk|rk)_live_[A-Za-z0-9]{24,128}
)
\b
pattern_requirements:

View file

@ -210,10 +210,10 @@ rand = { version = "0.10", optional = true }
[target.'cfg(all(windows, target_arch = "aarch64"))'.dependencies]
# ldap3's rustls backend still pulls ring 0.16, which fails to build on Windows ARM64.
# Use the platform TLS backend there to keep the raw LDAP validator available.
ldap3 = { version = "0.11.5", default-features = false, features = ["tls-native"], optional = true }
ldap3 = { version = "0.12.1", default-features = false, features = ["tls-native"], optional = true }
[target.'cfg(not(all(windows, target_arch = "aarch64")))'.dependencies]
ldap3 = { version = "0.11.5", default-features = false, features = ["tls-rustls"], optional = true }
ldap3 = { version = "0.12.1", default-features = false, features = ["tls-rustls-aws-lc-rs"], optional = true }
[dev-dependencies]
pretty_assertions = "1.4"

16
fuzz/Cargo.lock generated
View file

@ -142,6 +142,12 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "base32"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076"
[[package]]
name = "base64"
version = "0.22.1"
@ -1997,7 +2003,6 @@ dependencies = [
"hex",
"memchr",
"memmap2",
"once_cell",
"parking_lot",
"rustc-hash",
"schemars",
@ -2024,17 +2029,17 @@ name = "kingfisher-rules"
version = "0.1.0"
dependencies = [
"anyhow",
"base32",
"base64",
"crc32fast",
"hmac",
"ignore",
"include_dir",
"kingfisher-core",
"lazy_static",
"liquid",
"liquid-core",
"percent-encoding",
"rand 0.10.0",
"rand 0.10.1",
"regex",
"schemars",
"serde",
@ -2062,7 +2067,6 @@ dependencies = [
"http",
"kingfisher-core",
"kingfisher-rules",
"once_cell",
"parking_lot",
"regex",
"rustc-hash",
@ -2503,9 +2507,9 @@ dependencies = [
[[package]]
name = "rand"
version = "0.10.0"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8"
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
dependencies = [
"chacha20",
"getrandom 0.4.2",