mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-20 23:31:31 +02:00
Out-of-band testing is an instance setting — `off`, `self_hosted` or `public` — with the server, the token (the INTERACTSH API key row) and the wait resolved once in `shared/services/oast.py` and read on the stage thread. A mode that cannot be used is off and says why: self-hosted with no server, or public without the disclosure acknowledged. A fresh instance is off. `POST /oast/test` asks a public address for `/poll` over HTTPS and reports that the server answered, never that OAST works. The engine keeps one switch. `FieldNeeds` puts the resource key on the field and `GET /engines/catalog` fills `unavailable_reason`, so the builder renders the instance reason beside a switch that stays settable. Measured on nuclei v3.11.1: with `-no-interactsh` a check that needs a callback still loads and the request is refused — 0 requests, exit 0. So the batch reported COMPLETED and every origin in it read `scanned` for checks that never touched the target. The selection now drops them when nothing is listening, one coverage row reports the count and the reason, and `Tier.OAST` is left out of the planned tiers. Membership is what a check references, not what it is tagged: 615 of the 12,586 official rows reference an interactsh placeholder and 233 of those carry no `oast` tag. `vuln_templates.needs_oast` is parsed at index time; a library resync fills the column. The wait is paid on out-of-band batches alone, which sweep for 30 minutes so it is paid fewer times, and the tier names the server on its own rows. A finding's callback is rendered on the sheet from one label map; the list path is bared to the metadata. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
114 lines
4.1 KiB
Python
114 lines
4.1 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
|
|
from pydantic import BaseModel
|
|
from sqlalchemy import Column
|
|
from sqlalchemy.types import JSON
|
|
from sqlmodel import Field, SQLModel, UniqueConstraint
|
|
|
|
from shared.definitions.bounty_programs import (
|
|
DEFAULT_FEED_INTERVAL,
|
|
DEFAULT_SYNC_INTERVAL,
|
|
)
|
|
from shared.definitions.oast import (
|
|
DEFAULT_WAIT_SECONDS,
|
|
MAX_SERVER_LENGTH,
|
|
OastMode,
|
|
)
|
|
from shared.enums.instance import InstanceMode
|
|
from shared.utils.datetime import utc_now
|
|
|
|
SINGLETON_KEY = "instance"
|
|
|
|
|
|
class InstanceSettings(SQLModel, table=True):
|
|
__tablename__ = "instance_settings"
|
|
__table_args__ = (
|
|
UniqueConstraint("singleton_key", name="uq_instance_settings_singleton"),
|
|
)
|
|
|
|
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
|
|
singleton_key: str = Field(default=SINGLETON_KEY, max_length=20)
|
|
instance_name: str = Field(default="reNgine", max_length=120)
|
|
timezone: str = Field(default="UTC", max_length=64)
|
|
mode: str = Field(default=InstanceMode.BUG_BOUNTY.value)
|
|
onboarding_completed: bool = Field(default=False)
|
|
onboarding_completed_at: datetime | None = Field(default=None)
|
|
onboarding_completed_by: uuid.UUID | None = Field(default=None)
|
|
onboarding_step: int = Field(default=0)
|
|
onboarding_state: dict = Field(
|
|
default_factory=dict, sa_column=Column(JSON, nullable=False)
|
|
)
|
|
scan_history_retention_days: int = Field(default=90)
|
|
screenshot_retention_days: int = Field(default=30)
|
|
ai_enabled: bool = Field(default=False)
|
|
ai_provider: str | None = Field(default=None)
|
|
ai_model: str | None = Field(default=None)
|
|
ai_api_key_encrypted: str | None = Field(default=None)
|
|
ai_features: dict = Field(
|
|
default_factory=dict, sa_column=Column(JSON, nullable=False)
|
|
)
|
|
report_defaults: dict = Field(
|
|
default_factory=dict, sa_column=Column(JSON, nullable=False)
|
|
)
|
|
threat_intel_auto_sync: bool = Field(default=True)
|
|
cert_recheck_enabled: bool = Field(default=False)
|
|
bounty_sync_interval: str = Field(default=DEFAULT_SYNC_INTERVAL, max_length=16)
|
|
bounty_synced_at: datetime | None = Field(default=None)
|
|
bounty_events_seen_at: datetime | None = Field(default=None)
|
|
bounty_feed_interval: str = Field(default=DEFAULT_FEED_INTERVAL, max_length=16)
|
|
bounty_feed_synced_at: datetime | None = Field(default=None)
|
|
bounty_settings: dict = Field(
|
|
default_factory=dict, sa_column=Column(JSON, nullable=False)
|
|
)
|
|
mcp_enabled: bool = Field(default=False)
|
|
mcp_settings: dict = Field(
|
|
default_factory=dict, sa_column=Column(JSON, nullable=False)
|
|
)
|
|
new_checks_swept_at: datetime | None = Field(default=None)
|
|
oast_mode: str = Field(default=OastMode.OFF.value, max_length=16)
|
|
oast_server: str | None = Field(default=None, max_length=MAX_SERVER_LENGTH)
|
|
oast_public_acknowledged: bool = Field(default=False)
|
|
oast_wait_seconds: int = Field(default=DEFAULT_WAIT_SECONDS)
|
|
created_at: datetime = Field(default_factory=utc_now)
|
|
updated_at: datetime = Field(default_factory=utc_now)
|
|
|
|
|
|
class InstanceSettingsUpdate(BaseModel):
|
|
instance_name: str | None = None
|
|
timezone: str | None = None
|
|
mode: str | None = None
|
|
scan_history_retention_days: int | None = None
|
|
screenshot_retention_days: int | None = None
|
|
cert_recheck_enabled: bool | None = None
|
|
ai_enabled: bool | None = None
|
|
ai_provider: str | None = None
|
|
ai_model: str | None = None
|
|
ai_api_key: str | None = None
|
|
ai_features: dict | None = None
|
|
|
|
|
|
class InstanceSettingsRead(BaseModel):
|
|
id: uuid.UUID
|
|
singleton_key: str
|
|
instance_name: str
|
|
timezone: str
|
|
mode: str
|
|
onboarding_completed: bool
|
|
onboarding_completed_at: datetime | None
|
|
onboarding_completed_by: uuid.UUID | None
|
|
onboarding_step: int
|
|
onboarding_state: dict
|
|
scan_history_retention_days: int
|
|
screenshot_retention_days: int
|
|
cert_recheck_enabled: bool
|
|
ai_enabled: bool
|
|
ai_provider: str | None
|
|
ai_model: str | None
|
|
ai_api_key_masked: str | None
|
|
ai_configured: bool
|
|
ai_features: dict
|
|
capabilities: list[str]
|
|
created_at: datetime
|
|
updated_at: datetime
|