attackstr 0.1.1

Grammar-based security payload generation — TOML-driven, composable, encoding-aware
Documentation
# attackstr

Grammar-driven security payload generation for scanners, fuzzers, and taint-aware tooling.

`attackstr` loads TOML grammars, expands contexts and variables deterministically, applies built-in or custom encodings, and returns payloads with source metadata. It is designed for crates.io use, not just the wider Santh workspace.

## Features

- TOML grammar loading from strings or directories
- Configurable include/exclude/runtime filtering
- Built-in encoding transforms plus custom encoders
- Marker injection for taint-tracking payloads
- Streaming iterator API with `iter_payloads`
- Serde support across payload/config/grammar types
- Mutation helpers for lightweight evasive variants

## Installation

```toml
[dependencies]
attackstr = "0.1"
```

## Quick Start

```rust
use attackstr::{PayloadConfig, PayloadDb};

let mut db = PayloadDb::with_config(
    PayloadConfig::builder()
        .max_per_category(16)
        .deduplicate(true)
        .build(),
);

db.load_toml(
    r#"
[grammar]
name = "basic-xss"
sink_category = "xss"

[[contexts]]
name = "quoted-attr"
prefix = "\""
suffix = "\""

[[techniques]]
name = "svg-onload"
template = "<svg/onload={handler}>"

[[handlers]]
value = "alert(1)"
value = "confirm(1)"

[[encodings]]
name = "raw"
transform = "identity"
"#,
)?;

let payloads = db.payloads("xss");
assert_eq!(payloads.len(), 2);
assert!(payloads[0].text.contains("<svg/onload="));

# Ok::<(), attackstr::PayloadError>(())
```

## Grammar Format

Each grammar defines:

- `[grammar]` metadata
- `[[contexts]]` for prefix/suffix breakout wrappers
- `[[techniques]]` for templates
- `[[encodings]]` for final transforms
- `[[variables]]`-style arrays for substitution sets

Example:

```toml
[grammar]
name = "sql-basic"
sink_category = "sql-injection"
description = "Foundational SQLi payloads"
target_runtime = ["php", "node"]

[[contexts]]
name = "single-quoted"
prefix = "'"
suffix = "-- "

[[techniques]]
name = "boolean-tautology"
template = "{prefix} OR {tautology} {suffix}"
confidence = 0.95
expected_pattern = "(?i)sql|syntax|mysql"

[[tautologies]]
value = "1=1"
value = "'a'='a'"

[[encodings]]
name = "raw"
transform = "identity"

[[encodings]]
name = "url"
transform = "url_encode"
```

## Iterator APIs

Use cached category access when you want slices:

```rust
use attackstr::PayloadDb;

let mut db = PayloadDb::new();
db.load_toml(
    r#"
[grammar]
name = "demo"
sink_category = "cmdi"

[[techniques]]
name = "ping"
template = "; ping -c 1 {host}"

[[hosts]]
value = "127.0.0.1"
"#,
)?;

let payloads = db.payloads("cmdi");
assert_eq!(payloads.len(), 1);
# Ok::<(), attackstr::PayloadError>(())
```

Use streaming iteration when you want to avoid materializing the whole category:

```rust
use attackstr::PayloadDb;

let mut db = PayloadDb::new();
db.load_toml(
    r#"
[grammar]
name = "streaming"
sink_category = "xss"

[[techniques]]
name = "basic"
template = "<script>{call}</script>"

[[calls]]
value = "alert(1)"
value = "confirm(1)"
"#,
)?;

let streamed: Vec<_> = db.iter_payloads("xss").map(|payload| payload.text).collect();
assert_eq!(streamed.len(), 2);
# Ok::<(), attackstr::PayloadError>(())
```

For in-memory payload sets, `StaticPayloads` supports `iter()` and `iter_category()` as well.

## TOML Config End To End

`PayloadConfigFile` can load runtime behavior and grammar directories from TOML:

```rust
use attackstr::PayloadDb;

let temp = tempfile::tempdir()?;
let grammar_dir = temp.path().join("grammars");
std::fs::create_dir(&grammar_dir)?;

std::fs::write(
    grammar_dir.join("xss.toml"),
    r#"
[grammar]
name = "xss"
sink_category = "xss"

[[techniques]]
name = "basic"
template = "<script>alert(1)</script>"
"#,
)?;

std::fs::write(
    temp.path().join("attackstr.toml"),
    r#"
deduplicate = true
grammar_dirs = ["./grammars"]
"#,
)?;

let (mut db, errors) = PayloadDb::load_config_and_grammars(temp.path().join("attackstr.toml"))?;
assert!(errors.is_empty());
assert_eq!(db.payloads("xss").len(), 1);
# Ok::<(), attackstr::PayloadError>(())
```

## Custom Encodings

```rust
use attackstr::PayloadDb;

let mut db = PayloadDb::new();
db.register_encoding("reverse", |input| input.chars().rev().collect());

db.load_toml(
    r#"
[grammar]
name = "custom-encoding"
sink_category = "demo"

[[techniques]]
name = "one"
template = "abc"

[[encodings]]
name = "reversed"
transform = "reverse"
"#,
)?;

assert_eq!(db.payloads("demo")[0].text, "cba");
# Ok::<(), attackstr::PayloadError>(())
```

## Examples

Run the bundled examples:

```bash
cargo run --example basic
cargo run --example toml_config
```

## Development

- `cargo fmt`
- `cargo check`
- `cargo test`

Contribution workflow is documented in [CONTRIBUTING.md](./CONTRIBUTING.md).

## License

MIT