docs: Enhance module documentation across various files for clarity a… (#62)

* docs: Enhance module documentation across various files for clarity and completeness

* fix: Remove unnecessary blank line in build.rs for cleaner code

* docs: Update documentation to improve clarity and consistency in code comments
This commit is contained in:
Eli Peter 2026-05-02 17:46:45 -04:00 committed by GitHub
parent 40995e45e7
commit 1f2bfe76c1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 721 additions and 366 deletions

View file

@ -2793,7 +2793,7 @@ fn function_params(node: Node<'_>, bytes: &[u8]) -> Vec<String> {
params
}
/// Variant of [`function_params`] that always includes id-like typed
/// Variant of `function_params` that always includes id-like typed
/// Python params (`dag_id: str`, `dag_run_id: str`). Used by
/// `attach_route_handler` to populate `unit.params` for RouteHandler
/// units so middleware-injected auth checks (FastAPI
@ -2802,7 +2802,7 @@ fn function_params(node: Node<'_>, bytes: &[u8]) -> Vec<String> {
/// the id-shaped ones that are *the* primary user-controlled data on
/// REST routes.
///
/// The id-like filter in [`collect_param_names`] exists to keep
/// The id-like filter in `collect_param_names` exists to keep
/// internal helper signatures (`def f(release_id: int, project:
/// Project)`) from passing `unit_has_user_input_evidence`'s param
/// heuristic, which would over-fire `missing_ownership_check`. Route

View file

@ -1,4 +1,60 @@
#![doc = include_str!(concat!(env!("OUT_DIR"), "/auth_analysis.md"))]
//! Missing authorization and ownership checks (Rust-primary).
//!
//! Detects request handlers that reach a privileged operation taking a scoped
//! identifier (`*_id`, row reference, scoped resource) without a preceding
//! ownership or membership check.
//!
//! Other languages have rule scaffolding (`py.auth.*`, `js.auth.*`,
//! `rb.auth.*`, `go.auth.*`, `java.auth.*`) but only Rust has benchmark
//! corpus coverage and validated precision. Treat non-Rust findings as preview.
//!
//! # Rule IDs
//!
//! | Rule ID | Variant |
//! |---------|---------|
//! | `rs.auth.missing_ownership_check` | Standalone structural analyser (default on) |
//! | `rs.auth.missing_ownership_check.taint` | SSA/taint variant via `Cap::UNAUTHORIZED_ID` (default off) |
//!
//! Enable the taint variant via `scanner.enable_auth_as_taint = true` in
//! `nyx.conf`. Run both together when enabled; if both fire for the same site,
//! treat them as the same finding.
//!
//! # What counts as authorization
//!
//! The analyser accepts any of:
//! - A call to a recognised authorization helper (`check_ownership`,
//! `has_permission`, `require_*_member`, etc.; configurable per project).
//! - An ownership-equality check on a row reference
//! (`if owner_id != user.id { return 403 }`).
//! - A self-actor reference from a typed extractor param (`Extension<Session>`,
//! `CurrentUser`, etc.) combined with `user.id` / `user.user_id` use.
//! - A typed policy-guard wrapper (`GuardedData<ActionPolicy<X>, _>`);
//! configured via `policy_guard_names`.
//! - A SQL query joining through an ACL table or filtering by `user_id`
//! predicate (detected without a SQL parser via [`sql_semantics`]).
//! - A helper-summary lift: a called function whose body contains a
//! `require_*_member` call (fixed-point up to 4 iterations).
//!
//! # Sink classification
//!
//! | Class | Examples | Treatment |
//! |-------|---------|-----------|
//! | `InMemoryLocal` | `map.insert`, `vec.push` on local | Never a sink |
//! | `RealtimePublish` | `realtime.publish_to_group` | Sink unless channel scope is ownership-checked |
//! | `OutboundNetwork` | `http.post`, `reqwest::Client::post` | Sink unless sanitizer is on the path |
//! | `CacheCrossTenant` | `redis.set` with scoped keys | Sink unless tenant is checked |
//! | `DbMutation` | `db.insert`, `repo.save` with scoped IDs | Sink unless ownership is established |
//! | `DbCrossTenantRead` | `db.query` returning tenant-scoped rows | Sink unless ACL-join or tenant predicate is present |
//!
//! # Submodules
//!
//! - [`checks`]: ownership-check recognition, actor-context extraction,
//! row-field variable tracking
//! - [`config`]: per-language auth rule defaults and config merging
//! - [`extract`]: handler detection, scoped-ID extraction, summary lifting
//! - [`model`]: `AnalysisUnit`, `AuthCheck`, `SensitiveOperation`, `SinkClass`
//! - [`sql_semantics`]: ACL-join and `user_id`-predicate detection without a
//! SQL parser
pub mod checks;
pub mod config;

View file

@ -253,7 +253,7 @@ pub struct AnalysisUnit {
/// Function parameter names whose static type maps to a
/// payload-incompatible scalar ([`crate::ssa::type_facts::TypeKind::Int`]
/// or [`crate::ssa::type_facts::TypeKind::Bool`]). Populated
/// per-file by [`super::apply_typed_bounded_params`] using the
/// per-file by `apply_typed_bounded_params` using the
/// SSA-derived `VarTypes` map. Consulted by
/// `is_typed_bounded_subject` so parameters like Spring `Long
/// userId`, Axum `Path<i64>`, or FastAPI `user_id: int` are not
@ -265,7 +265,7 @@ pub struct AnalysisUnit {
/// declared type is a payload-incompatible scalar. Map key is the
/// parameter name (e.g. `dto`), value is the list of field names
/// (e.g. `["age", "count"]`). Populated by
/// [`super::apply_typed_bounded_params`] only when the parameter
/// `apply_typed_bounded_params` only when the parameter
/// itself was recognised as a typed extractor, bare parameters
/// with no framework gate never lift their fields.
pub typed_bounded_dto_fields: HashMap<String, Vec<String>>,