CodeQL 2.26.1 added barriers to Rust’s hard-coded cryptographic value queries, reducing false positives where a literal does not represent a secret used by the application. Teams using CodeQL for Rust may see fewer alerts after updating the analysis bundle.

That is good signal improvement, but it should not turn into a blanket dismissal rule. Test vectors, public constants, initialization vectors, salts, private keys, API tokens, and encryption keys can all look like strings or byte arrays while having very different security meaning.

Quick answer

Classify every flagged value by purpose and environment. Public test data can stay in source with a clear label. A credential or production cryptographic key must come from a managed secret source, have a rotation path, and never appear in repository history.

use std::env;

fn encryption_key() -> Result<Vec<u8>, String> {
    let encoded = env::var("APP_ENCRYPTION_KEY")
        .map_err(|_| "APP_ENCRYPTION_KEY is missing".to_string())?;

    let key = hex::decode(encoded)
        .map_err(|_| "APP_ENCRYPTION_KEY must be valid hex".to_string())?;

    if key.len() != 32 {
        return Err("APP_ENCRYPTION_KEY must contain 32 bytes".to_string());
    }
    Ok(key)
}

An environment variable is only an input mechanism. Production should inject it from a secret manager and restrict which workload can read it.

What the CodeQL change means

A static query models paths from literals into cryptographic operations. Barriers stop flows that analysis can determine do not represent a vulnerable use. Improving those barriers reduces review fatigue and makes a remaining result more useful.

It does not retroactively prove that removed findings are harmless. Query behavior can change because of modeling, while your threat model depends on whether a value needs confidentiality, uniqueness, unpredictability, or only reproducibility.

Separate public values from secrets

Public algorithm identifiers and protocol constants are expected in code. Published test vectors are also safe to commit when they are clearly limited to tests.

#[cfg(test)]
const RFC_TEST_KEY: [u8; 16] = [
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
];

Name the standard and section in a comment. Keep the value under test-only compilation where possible. Avoid realistic variable names such as PROD_KEY, even for fake data, because they confuse scanners and reviewers.

Private keys, signing keys, database credentials, session secrets, and fixed encryption keys are different. Removing the current line is insufficient if Git history, package artifacts, logs, or container layers still contain it.

Review a remaining alert

Trace the value to its use and answer:

  • Does security require this value to be secret?
  • Must it be unique per user, message, deployment, or environment?
  • Can a repository reader impersonate a service or decrypt data?
  • Is it production code, example code, generated code, or a test?
  • Is rotation possible without rebuilding and redeploying everything?

For nonces and IVs, secrecy may not be required, but uniqueness often is. A hard-coded all-zero nonce can be dangerous even though hiding it would not fix the design.

Respond when a real secret was committed

Revoke or rotate it first. Then remove it from current source, investigate use, and decide whether history rewriting is justified. Add a secret-scanning control and a test that confirms the application fails closed when the managed secret is absent.

Do not print the value while debugging the migration. Log a secret version identifier or fingerprint only if the operational need is clear and the output cannot help recover the secret.

Verify the CodeQL upgrade

Run analysis on the same commit before and after the CodeQL bundle update. Save the result counts and inspect changed findings, especially those that disappear. This separates query-model changes from code changes.

Keep a small repository fixture with one known real hard-coded key and one published test vector. It provides a practical signal that your configuration detects the dangerous case without flooding reviewers with the harmless one.

Run that fixture after every CodeQL bundle update.

Primary sources

Fewer alerts are valuable when they improve reviewer attention. Preserve that value by classifying literals by security purpose, keeping test vectors unmistakably test-only, and rotating any real secret instead of merely teaching the scanner to ignore it.