UOF - Unicode Obfuscation Fine-tune

UOF is an experimental, compact supervised fine-tune for inspecting Unicode-bearing text and returning a structured obfuscation analysis. This release is a LoRA adapter for Qwen/Qwen3-0.6B-Base, intended for research, experimentation, and defensive tooling prototypes.

The adapter is not a merged standalone model. Load the Qwen base model and attach this adapter with PEFT.

Model summary

  • Model type: PEFT LoRA adapter for causal text generation.
  • Base model: Qwen/Qwen3-0.6B-Base.
  • Adapter: NewSonnet/unicode-obfuscation-finetune-0.6b.
  • Task: map an ASCII-escaped observed value plus its context to one strict JSON analysis object.
  • Contexts: display_text, identifier, filename, and url.
  • Repository: https://github.com/EF-Code/unicode-obfuscation-finetune

Intended use

UOF is designed to make Unicode-bearing strings easier to inspect in logs, code review, and defensive preprocessing experiments. It can identify the small set of features represented in its synthetic data, explain the label, show code points, and propose a normalized or conservative rewrite for human review.

It is not a replacement for a Unicode security library, an IDNA validator, a sanitizer, an allowlist, or an analyst. Treat every result as an analysis hint and keep enforcement in independently reviewed application code.

Input and output contract

The model expects an explicit context and an ASCII-escaped observed value:

Context: identifier
Observed value: pay\u202epayload\u202c

It was trained to return exactly one JSON object with these keys:

{
  "risk": "dangerous",
  "categories": ["bidi_control"],
  "normalized_escaped": "pay\\u202epayload\\u202c",
  "safe_rewrite_escaped": "paypayload",
  "skeleton": "paypayload",
  "codepoints": ["U+0070", "U+0061", "U+0079", "U+202E"],
  "explanation": "Directional control characters can change visual order or hide the apparent text."
}

The risk label is one of benign, suspicious, or dangerous. Text-valued output fields are kept ASCII-escaped. The category vocabulary currently includes bidi_control, confusable, invisible, mixed_script, and normalization_change.

Risk is context-sensitive: a legitimate multilingual display string is not automatically suspicious, while a mapped cross-script confusable in an identifier, filename, or URL is treated more strictly by the labeling rules.

Coverage

The training records cover:

  • invisible formatting characters;
  • bidirectional controls;
  • a small mapped set of cross-script confusables;
  • fullwidth and other compatibility changes;
  • decomposed forms that change under normalization; and
  • benign multilingual display text.

The confusable mapping is deliberately small and explainable. It is not a complete implementation of Unicode confusables or the Unicode Security Mechanisms data.

Training data

The dataset is synthetic and generated by a deterministic rule engine. Labels are not LLM-invented. Each record contains a context, mutation kind, ASCII-escaped observation, prompt, completion, and structured target.

The run used the following splits:

Split Records
Train 1,200
Validation 200
Test 200
Total 1,600

The public source repository contains the canonical deterministic generator (version uof-dataset-v1), validator, and unit tests. The exact JSONL files created in Google Drive for this run are not included in this model repository; the published counts, seed, and audit checks document the run while avoiding publication of generated artifacts by default.

Training procedure

Training was performed in Google Colab on one Tesla T4 GPU. The base model was loaded in 4-bit mode and adapted with LoRA using Unsloth, PEFT, and TRL.

Setting Value
Base model Qwen/Qwen3-0.6B-Base
Fine-tuning method LoRA supervised fine-tuning
Epochs 2
Optimizer steps 150
Per-device batch size 2
Gradient accumulation 8
Effective batch size 16
Learning rate 2e-4
Maximum sequence length 1024
Precision fp16
Optimizer AdamW 8-bit
Loss completion-only
LoRA rank / alpha / dropout 16 / 32 / 0.0
LoRA target modules q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj
Measured training time 572.9555 seconds
Final validation loss 0.013275

Observed software versions in the run were Python 3.13.15, PyTorch 2.11.0+cu128, Transformers 5.5.0, Datasets 4.3.0, TRL 0.24.0, Unsloth 2026.9.4, and PEFT 0.20.0.

Evaluation

The reported evaluation is a small held-out synthetic smoke test, not a benchmark and not evidence of production generalization. The model generated greedily on the first 12 rows of the synthetic test split. A JSON object was extracted and parsed when possible.

Metric Result
Test rows sampled 12
Parseable outputs 11 / 12
Complete target matches 2 / 11 parseable
Correct risk labels 7 / 11 parseable

The exact-match and risk-label denominators exclude the one output that was not parseable. These numbers should not be used as production detection accuracy, calibration, or a security guarantee.

How to use

Install compatible versions of PyTorch, Transformers, and PEFT. Load the base model and adapter separately:

import torch
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer

base_id = "Qwen/Qwen3-0.6B-Base"
adapter_id = "NewSonnet/unicode-obfuscation-finetune-0.6b"

tokenizer = AutoTokenizer.from_pretrained(adapter_id)
base = AutoModelForCausalLM.from_pretrained(
    base_id,
    torch_dtype="auto",
    device_map="auto",
)
model = PeftModel.from_pretrained(base, adapter_id)

prompt = (
    "You are UOF, a Unicode-obfuscation analyzer.\n"
    "Inspect the ASCII-escaped value below in its stated context.\n"
    "Context: identifier\n"
    "Observed value: pay\\u202epayload\\u202c\n\n"
    "Return exactly one JSON object with these keys: risk, categories, "
    "normalized_escaped, safe_rewrite_escaped, skeleton, codepoints, explanation.\n"
    "Use risk one of benign, suspicious, dangerous. Keep all text fields "
    "ASCII-escaped. Do not use Markdown or add extra keys."
)

inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
with torch.inference_mode():
    output = model.generate(
        **inputs,
        max_new_tokens=180,
        do_sample=False,
    )

completion = output[0, inputs["input_ids"].shape[-1]:]
print(tokenizer.decode(completion, skip_special_tokens=True))

Depending on the runtime, adjust dtype and device placement. The adapter requires the base model; it cannot be loaded as a complete model by itself.

Limitations and safety

  • The labels are synthetic and deterministic. They demonstrate the task contract, not real-world coverage or calibrated probability.
  • The confusable map is intentionally small. Unicode versions, scripts, normalization behavior, and application policies can expose cases absent from this release.
  • A language model can emit malformed JSON, miss a code point, or provide an unsafe rewrite. Validate the schema and independently inspect the original code points before acting.
  • Safe rewrite is only a suggestion. It can be lossy, and it must not silently replace the original value in authentication, payments, package distribution, URL handling, or other security-sensitive workflows.
  • Benign multilingual text and shaping controls can be legitimate. Avoid treating non-ASCII text as suspicious merely because it is non-ASCII.
  • This adapter must not be the sole control for a security decision.
  • No adapter-specific license is declared in this release. The Qwen base model has separate terms; review those terms before redistribution or deployment.

Provenance and reproducibility

Citation

If you use this experiment, cite the repository and adapter URL above. There is no accompanying paper or formal benchmark for this release.

Downloads last month
28
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for NewSonnet/unicode-obfuscation-finetune-0.6b

Adapter
(75)
this model