project-snmp-trap-profiles-authoring — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited project-snmp-trap-profiles-authoring (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this skill before editing files under:
src/go/plugin/go.d/config/go.d/snmp.trap-profiles/src/go/cmd/snmptrapprofilegen/ (shipped helper source).agents/sow/specs/snmp-traps/netdata.md (when the change touches profile schema or trap subsystem decisions that the profiles encode)The authoritative schema reference is src/go/plugin/go.d/config/go.d/snmp.trap-profiles/profile-format.md. The authoritative subsystem design is .agents/sow/specs/snmp-traps/netdata.md. This skill is the working checklist that keeps repository edits aligned with both.
The SNMP trap SOW spec directory intentionally separates Netdata product contracts from research evidence.
.agents/sow/specs/snmp-traps/:
netdata.mdtrap-metrics-profiles.mdnetdata-snmp-hub-architecture.mddecisions/.agents/sow/specs/snmp-traps/research/:domain/ for general SNMP trap observability research;playbooks/ for operational playbooks and skill-distillation sourcematerial;
netdata-existing/ for inventories of existing Netdata subsystems used asdesign inputs;
external-systems/ for per-product studies of other trap implementations;comparison/ for cross-system matrices, stress tests, and synthesis.Do not put new research files beside the Netdata specs. Research can inform specs, but it is not itself a Netdata product contract. When a research finding becomes a product rule, copy the accepted rule into a top-level spec or decisions/ entry and cite the research path as evidence.
.0. toleranceProfile authors should use the canonical trap OID form produced by the source MIB/tooling. The receiver lookup is exact-match-first and then tolerates the SMIv1 / SMIv2 trap-OID ambiguity by adding or removing a single .0. segment immediately before the final OID arc on primary miss. This tolerance is trap-OID-only: do not normalize or alternate-match varbind OIDs.
name:field uses the canonical SMI form <MIB-MODULE>::<symbol> (e.g. IF-MIB::linkDown, CISCO-CONFIG-MAN-MIB::ccmCLIRunningConfigChanged). Vendors reuse bare symbolic names across product-line MIB modules; the bare symbol is NOT globally unique. The qualified form matches what snmptranslate / snmptrapd / MIB browsers produce and is what the plugin writes to the TRAP_NAME journal field. Rule: if the OID changes, the name: slug MUST change.
varbinds:list MUST exist in the file-scoped varbinds: table or be an inline dict on the trap entry. Dangling name references are a bug — they render as empty values in restricted templates and produce misleading journal messages.
MAX-ACCESS. not-accessible index objects must still be declared in the table (they ship inside TRAP_JSON and, when non-sensitive/non-redundant, indexed TRAP_VAR_* fields), but never as a description: template variable on its own — varbinds an SNMP entity will not send in a trap PDU never resolve at runtime.
Varbind records with resolved: false (the MIB-extractor couldn't resolve the OBJECT-TYPE through the IMPORTS chain) MUST be dropped from both the table and the per-trap reference list. An empty {} entry under varbinds: violates the schema and is rejected by the plugin at profile load.
category must be one ofstate_change, config_change, security, auth, license, mobility, diagnostic, unknown. Do not introduce new categories. Cross-cutting concerns (compliance scope, tenant, datacenter, change window…) belong in labels:, not as new category slugs. Operator-authored OIDs default to unknown and the operator overrides category/severity/labels in plugin config — there is no separate "custom" category slug.
severitymust be one of emerg, alert, crit, err, warning, notice, info, debug (full names — not warn). The plugin maps these to PRIORITY=0..7 on the journal entry. emerg is reserved for true vendor catastrophe; default to warning/notice/info for routine events. debug is rare and only for traps the MIB itself marks as debug-level.
bounded-cardinality varbinds only. Reject (do not commit) labels that reference MAC addresses, source IPs, usernames, packet contents, RAID slot IDs, or any per-event identifier. High-cardinality content belongs in description: (rendered into MESSAGE), indexed TRAP_VAR_* journal fields, and TRAP_JSON, not in metric-propagating labels.
profile labels: AND operator config labels:) emit as TRAP_TAG_<KEY_UPPERCASE> journal fields. The dedicated TRAP_TAG_* namespace removes any risk of collision with the plugin-controlled TRAP_* field set (TRAP_OID, TRAP_NAME, TRAP_CATEGORY, etc. — see spec §11). The only remaining validation is the lowercase-key syntax rule ([a-z][a-z0-9_]*). Pick label keys that read clearly.
src/go/plugin/go.d/config/go.d/snmp.trap-profiles/default/ are stock vendor-curated profiles, regenerated by src/go/cmd/snmptrapprofilegen/ and shipped from Netdata as /usr/libexec/netdata/plugins.d/snmp-trap-profile-gen. Do not hand-edit them for site-specific concerns; site overrides belong under /etc/netdata/go.d/snmp.trap-profiles/ and are documented in profile-format.md § "Operator overrides".
profiles may define optional trap-to-metric rules only through the schema in src/go/plugin/go.d/config/go.d/snmp.trap-profiles/profile-format.md. Listener jobs decide enablement with profile_metrics. Do not add ad hoc metric fields, unbounded labels, or site-specific metric choices to stock profiles. Site-specific metric rules belong in operator profile files under /etc/netdata/go.d/snmp.trap-profiles/.
Required profile-metric authoring checks:
counter, sample, and state; use canonicalfields for stock/generated profiles and keep compact aliases for operator-authored examples.
where: predicates are ANDed and may use equals, in, exists,absent, greater_than, less_than, range, and not; never combine not with exists or absent, and never define a predicate without a condition operator.
sample rules may read only numeric varbind types documented inprofile-format.md; TimeTicks is converted to seconds before scale. Counter32, Counter64, and TimeTicks are valid for sample rules, not resource identity keys.
state rules use either separate problem_trap / clear_trap OIDs orsame-OID state.set_when / state.clear_when predicates. state.ttl must be a valid Go duration string, and state.ttl_behavior currently supports only clear_and_expire.
identity.resource.key_from_varbind MUST reference an integer-likebounded varbind (INTEGER, Integer32, Unsigned32, or Gauge32). Never use strings, MACs, usernames, addresses, payloads, or event IDs as metric resource keys.
resource and non-resource rules in one chart, and do not mix multiple resource classes in one chart.
lifecycle settings. Expired series are removed; if the same identity appears again, the next committed trap creates a fresh series.
missing: unknown_dimension is allowed only with resource identity.missing: drop increments rule-miss diagnostics; missing: error increments extraction-failure diagnostics.
built-in receiver charts, the built-in profile_metric_diagnostics chart, or any other loaded profile rule/chart. Reserved metric prefixes include snmp_trap_events_, snmp_trap_severity_, snmp_trap_errors_, snmp_trap_dedup_, snmp_trap_pipeline_, snmp_trap_source_, snmp_trap_sources_, snmp_trap_metric_, and snmp_trap_profile_metrics_. Built-in source receiver metrics are automatic; profile rules should describe vendor or site semantics, not duplicate receiver pipeline health.
auto_safe: true means the rule is safe for broad trap hubs: boundedlabels, bounded resource identity, no sensitive values, and no surprising high cardinality. Stock rules need review evidence before enabling it.
the configured journal and/or OTLP backend. Dedup-suppressed and write-failed traps do not update profile metrics.
TRAP_VAR_* journal fields automatically from received non-sensitive, non-redundant event varbinds, and keeps the structured audit copy in TRAP_JSON. There is no profile knob to hand-author per-OID journal field names.
profile-format.mddocuments display_hint (e.g. 1x: for MAC, 1d.1d.1d.1d for IPv4) as a future varbind field. The extractor keeps display hints in intermediate JSONL when gomib exposes them, but the stock profile emitter does not write display_hint today. Do not add display_hint keys by hand to stock profiles — they would be silently overwritten on regeneration. When the plugin's renderer needs display-hint formatting, the emitter and loader will be updated in the same regeneration cycle.
src/go/cmd/snmptrapprofilegen/)as snmp-trap-profile-gen, installed under usr/libexec/netdata/plugins.d/, and packaged in the plugin-go component. Do not add Python, CGO, SQLite, or runtime MIB compiler dependencies to the shipped operator path.
load as one global MIB universe. Keep the batch-based gomib loading path, deterministic source priority, duplicate-module source-conflicts.json, OID-level conflicts.json, and bounded memory validation. If source discovery changes, rerun at least a representative multi-vendor corpus before touching the stock pack.
JSONL keyed by the classifier input hash. Do not switch to SQLite or another opaque cache for committed or CI-reviewed state.
against the JSON Schema and the semantic validators: closed category, closed severity, exact template helper allowlist, and uniform description style ending with on {{hostname}}.. Retry invalid responses up to five total attempts before mechanical fallback, or hard failure under --require-llm.
default/. It must:name: as <MIB-MODULE>::<symbol> so theslug is globally unique;
inline varbinds — see netdata.md §7 and profile-format.md);
oid (extractor'sresolved: false cases) from both the table and the per-trap reference list — never emit empty {} table entries;
enrichment_source,enrichment_attempts) from the YAML output;
catalogue.json in sync (operator grep-before-install tool);OID then name) so regenerations produce reviewable diffs.
installs src/go/plugin/go.d/config/go.d/snmp.profiles/metadata/iana-enterprise-numbers.txt under usr/lib/netdata/conf.d/go.d/snmp.profiles/metadata/. --refresh-pen may fetch the current IANA registry when explicitly requested.
cd src/go
go run ./cmd/snmptrapprofilegen generate \
--source-dir /path/to/mibs \
--all \
--classify \
--require-llm \
--concurrency 20 \
--out-dir /tmp/snmp-trap-profile-gen-output \
--profiles-out-dir ../../src/go/plugin/go.d/config/go.d/snmp.trap-profiles/default \
--catalogue ../../src/go/plugin/go.d/config/go.d/snmp.trap-profiles/catalogue.jsonThe installed operator equivalent is:
/usr/libexec/netdata/plugins.d/snmp-trap-profile-gen generate \
--source-dir ./mibs \
--all \
--out-dir ./snmp-trap-profile-gen-outputThe shipped pack lives under src/go/plugin/go.d/config/go.d/snmp.trap-profiles/default/. Operator output should be copied from snmp-trap-profile-gen-output/profiles/ into /etc/netdata/go.d/snmp.trap-profiles/.
These are closed sets enforced in three places that must stay in sync:
src/go/cmd/snmptrapprofilegen/main.go — validCategories,validSeverities, severityPriority, JSON Schema, and classifier prompt text.
src/go/plugin/go.d/config/go.d/snmp.trap-profiles/profile-format.md— the operator-facing category and severity tables.
.agents/sow/specs/snmp-traps/netdata.md — §3 (category taxonomy) and§11 (PRIORITY mapping).
A taxonomy change without all three updates is incomplete and will be rejected at review. Any taxonomy change also requires a re-run of the Go helper's classification path against the full corpus (the existing classifications were done under the prior taxonomy and are now stale).
Stock profile YAMLs stay raw in the repository so changes are reviewable in git diff. Installed/package stock vendor profiles MUST be compressed as .yaml.zst; the runtime loader supports raw .yaml, compressed .yaml.zst, and draft-era .yaml.gz compatibility. Operator/user profiles under /etc/netdata/go.d/snmp.trap-profiles/ SHOULD stay uncompressed .yaml for editability. If a single vendor file grows past ~10 MB in the repository, revisit description verbosity rather than hiding unreviewable generated bloat behind compression.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.