{% extends "/base.html" %} {% block title %}{{ result.target }} (ランク{{ result.rank }}) - Nercone TLS Test{% endblock %} {% block title_suffix %}TLS Test{% endblock %} {% block description %}Nercone TLS Test の結果ページです。対象: {{ result.target }} / スコア: {{ "%.1f"|format(result.score or 0) }} / ランク: {{ result.rank }}。{% endblock %} {% block header_desc %}ただのTLS/SSL設定分析サービス{% endblock %} {% block extra_head %} {% endblock %} {# ------------------------------------------------------------------ Replace the site header with a results banner that carries the rank badge, target, metadata, action buttons, and the tab bar at its foot. ------------------------------------------------------------------ #} {% block custom_header %} {% set rank_color_map = { 'SSS': 'bright-green', 'SS': 'bright-green', 'S': 'bright-green', 'A': 'green', 'B': 'green', 'C': 'green', 'D': 'bright-yellow', 'E': 'bright-yellow', 'F': 'bright-yellow', 'G': 'yellow', 'H': 'yellow', 'I': 'yellow', 'J': 'bright-orange', 'K': 'bright-orange', 'L': 'bright-orange', 'M': 'orange', 'N': 'orange', 'O': 'bright-red', 'P': 'bright-red', 'Q': 'red', 'R': 'bright-purple' } %} {% set rank = result.rank or job.rank or '?' %} {% set rank_color = rank_color_map.get(rank, 'tx') %}
{{ rank }} {{ "%.0f"|format(result.score or job.score or 0) }}

{{ result.target or job.target }}

実行日時 {{ finished_at_display or job.finished_at or "—" }} 所要時間 {{ "%.0f"|format((result.duration or 0) * 1000) }}ms

{{ test_id }}

{% if result.error %}

{{ result.error }}

{% endif %}
{% endblock %} {% block content %} {# Log row for a finding. Columns: [step] severity-label + title(white) detail(gray) #} {% macro finding_row(f) -%}
[{{ (f.step or f.group or f.category or 'info')|replace('_','-')|lower }}] {{ f.severity_label|upper }} {{ f.title }} {{ f.detail or '' }}
{%- endmacro %} {# A boolean row rendered with green/red text. #} {% macro yn(value, ok='対応', bad='未対応') -%} {% if value %}{{ ok }}{% else %}{{ bad }}{% endif %} {%- endmacro %} {# Revocation cell (OCSP / CRL). Translates the technical error strings from certs/revocation.py into a single clean Japanese label, so we never print awkward combinations like 「未確認 no OCSP URL」. #} {% macro rev_cell(r, kind) -%} {%- if not r -%} {%- elif r.checked and not r.revoked -%} Not Revoked {%- if r.source %} ({{ r.source }}){% endif -%} {%- elif r.checked and r.revoked -%} Revoked {%- if r.reason %} ({{ r.reason }}){% endif -%} {%- else -%} {%- set err = (r.error or '')|string -%} {%- if 'no OCSP URL' in err or 'no AIA' in err -%} {{ kind }} URL が提供されていません {%- elif 'no CRL DP' in err or 'no http CRL URL' in err -%} {{ kind }} URL が提供されていません {%- elif 'all CRLs unreachable' in err -%} {{ kind }} レスポンダに到達できません {%- elif err -%} 確認失敗 ({{ err }}) {%- else -%} 未確認 {%- endif -%} {%- endif -%} {%- endmacro %}
{# -------- 概要 -------- #}
{% if summary %} {% for f in summary %}{{ finding_row(f) }}{% endfor %} {% else %}
[info]該当項目なし
{% endif %}
{# -------- 信頼性 -------- #}
{# Certificate chain table #} {% set chain = result.data.certificate_chain if result.data else [] %} {% if chain %}

証明書チェーン

{% for c in chain %} {% endfor %}
#CN / Subject発行者有効期限署名
{{ loop.index }}
{{ c.common_name or c.subject or '—' }}
{% if c.sans %}
SAN: {{ (c.sans or [])|join(', ') }}
{% endif %}
{{ c.issuer or '—' }}
{{ c.not_after or '—' }}
{% if c.is_expired %}期限切れ {% elif c.days_until_expiry is defined and c.days_until_expiry is not none %}残 {{ c.days_until_expiry }} 日{% endif %}
{{ (c.signature_hash_algorithm or '—')|upper }} {{ c.public_key_algorithm or '—' }}{% if c.public_key_size_bits %} {{ c.public_key_size_bits }}-bit{% endif %} {% if c.public_key_curve %} ({{ c.public_key_curve }}){% endif %}
{% endif %} {# Trust stores #} {% set trust = result.data.trust if result.data else [] %} {% if trust %}

プラットフォームごとの信頼状況

{% for t in trust %} {% endfor %}
プラットフォーム信頼状況
{{ t.platform }} {{ yn(t.trusted, '信頼', '未信頼') }} {{ t.error or '—' }}
{% endif %} {# Revocation + HSTS + CAA summary #} {% set ocsp = (result.data or {}).get('ocsp') %} {% set crl = (result.data or {}).get('crl') %} {% set hsts = (result.data or {}).get('hsts') %} {% set caa = (result.data or {}).get('caa') %} {% set preload = (result.data or {}).get('preload') %}

失効・HSTS・CAA

OCSP{{ rev_cell(ocsp, 'OCSP') }}
CRL{{ rev_cell(crl, 'CRL') }}
HSTS {%- if not hsts or hsts.error -%} {%- elif hsts.present -%} 有効 max-age={{ hsts.max_age }}{% if hsts.include_subdomains %}; includeSubDomains{% endif %}{% if hsts.preload %}; preload{% endif %} {%- else -%} 無効 {%- endif -%}
HSTS preload {%- if preload -%} {%- for p in preload -%} {{ p.browser }}: {{ yn(p.listed, 'Listed', 'Not listed') }}{% if not loop.last %} · {% endif %} {%- endfor -%} {%- else -%} {%- endif -%}
CAA {%- if not caa -%} {%- elif caa.records -%} {{ caa.records|length }} 件 ({{ caa.effective_host }})
{{ caa.records|join('; ') }}
{%- else -%} 未設定 {%- endif -%}

信頼性に関するすべてのログ

{% set findings = groups['reliability'] %} {% if findings %}{% for f in findings %}{{ finding_row(f) }}{% endfor %} {% else %}
[info]項目なし
{% endif %}
{# -------- 安全性 -------- #}
{# Protocol versions #} {% set versions = (result.data or {}).get('versions') %} {% if versions %}

対応プロトコル

{% for name, ok in versions.items() %} {% endfor %}
バージョン対応
{{ name }}{{ yn(ok, '有効', '無効') }}
{% endif %} {# Accepted ciphers per version #} {% set ciphers = (result.data or {}).get('ciphers') %} {% if ciphers %}

受理された暗号スイート

{% for name, cs in ciphers.items() %} {% if cs %}

{{ name }} ({{ cs|length }})

    {% for c in cs %}
  • {{ c }}
  • {% endfor %}
{% endif %} {% endfor %}
{% endif %} {# Named groups #} {% set groups_list = (result.data or {}).get('named_groups') %} {% if groups_list %}

TLS 1.3 鍵交換グループ

{% for g in groups_list %}{{ g }}{% if not loop.last %}, {% endif %}{% endfor %}

{% endif %}

安全性に関するすべてのログ

{% set findings = groups['safety'] %} {% if findings %}{% for f in findings %}{{ finding_row(f) }}{% endfor %} {% else %}
[info]項目なし
{% endif %}
{# -------- 脆弱性 -------- #}
{% set hb = (result.data or {}).get('heartbleed') %} {% set ccs = (result.data or {}).get('ccs_injection') %} {% set renego = (result.data or {}).get('secure_renegotiation') %} {% set scsv = (result.data or {}).get('fallback_scsv') %}

既知脆弱性の判定

脆弱性判定詳細
Heartbleed{% if hb %}{{ yn(not hb.vulnerable, '影響なし', '影響あり') }}{% else %}{% endif %}{% if hb %}{% if hb.heartbeat_extension %}Heartbeat advertised{% endif %}{% if hb.error %} {{ hb.error }}{% endif %}{% endif %}
CCS Injection{% if ccs %}{{ yn(not ccs.vulnerable, '影響なし', '影響あり') }}{% else %}{% endif %}{{ (ccs or {}).get('detail','') }}
Secure Renegotiation{% if renego %}{{ yn(renego.supported, '対応', '未対応') }}{% else %}{% endif %}{{ (renego or {}).get('detail','') }}
TLS_FALLBACK_SCSV{% if scsv %}{{ yn(scsv.supported, '対応', '未対応') }}{% else %}{% endif %}{{ (scsv or {}).get('detail','') }}

脆弱性に関するすべてのログ

{% set findings = groups['vulnerabilities'] %} {% if findings %}{% for f in findings %}{{ finding_row(f) }}{% endfor %} {% else %}
[info]項目なし
{% endif %}
{# -------- 互換性 -------- #}
{% set http = (result.data or {}).get('http') %} {% set http3 = (result.data or {}).get('http3') %} {% set alpn = (result.data or {}).get('alpn') %}

HTTP プロトコル対応

{% if http and http.server %}{% endif %} {% if http and http.alt_svc %}{% endif %}
HTTP/1.1{% if http %}{{ yn(http.http1, '対応', '未対応') }}{% else %}{% endif %}
HTTP/2{% if http %}{{ yn(http.http2, '対応', '未対応') }}{% else %}{% endif %}
HTTP/3 (QUIC){% if http3 %}{{ yn(http3.supported, '対応', '未対応') }}{% if http3.error %} {{ http3.error }}{% endif %}{% else %}{% endif %}
ALPN{% if alpn %}{{ alpn }}{% else %}{% endif %}
Server{{ http.server }}
Alt-Svc{{ http.alt_svc }}
{% set sim = (result.data or {}).get('handshake_simulation') %} {% if sim %}

ハンドシェイクシミュレーション

{% for s in sim %} {% endfor %}
クライアント結果プロトコル暗号備考
{{ s.client }} {{ yn(s.connected, 'OK', 'Fail') }} {{ s.negotiated_version or '—' }} {{ s.negotiated_cipher or '—' }} {{ s.error or '' }}
{% endif %}

互換性に関するすべてのログ

{% set findings = groups['compatibility'] %} {% if findings %}{% for f in findings %}{{ finding_row(f) }}{% endfor %} {% else %}
[info]項目なし
{% endif %}
{# -------- ログ -------- Replays the live processing log: interleaved progress rows (from test_progress table) and findings (grouped by step). #}
{% if log_entries %} {% for e in log_entries %} {% if e.kind == 'phase' %}
[{{ (e.phase or 'info')|replace('_','-')|lower }}] {{ e.detail or '' }}
{% else %} {{ finding_row(e.finding) }} {% endif %} {% endfor %} {% else %}
[info]ログが記録されていません
{% endif %}
{# -------- JSON -------- #}
GET /api/tools/tls-test/results/{{ test_id }}
{{ result | tojson(indent=2) }}
{% endblock %}