# Nodes with No Password

> This report identifies active PeopleSoft message nodes that have no authentication configured or have authentication enabled but no passwords set.

---

Site [llms.txt](/llms.txt)

---

<div class="alert alert-primary border shadow-sm mb-4 psl-prospect-cta" role="note">
  <div class="d-flex flex-column flex-lg-row align-items-lg-center justify-content-between gap-3">
    <div>
      <strong>New to psLens?</strong> This page documents one specific report. To see how it runs in the product, what
      the output looks like, and how teams use it in practice, start with a live walkthrough.
    </div>
    <div class="d-flex flex-wrap gap-2">
      <a class="btn btn-sm btn-primary" href="/contact/">Book a Demo</a>
      <a class="btn btn-sm btn-outline-primary" href="/docs/reports/">Browse Reports</a>
    </div>
  </div>
</div><div id="pslens-context-panel" class="card border-info mb-4 d-none">
  <div class="card-header bg-light text-info py-2 fw-bold d-flex align-items-center border-bottom border-info-subtle">
    <i class="bi bi-info-circle-fill me-2"></i>
    <span>Tailored Operational Context</span>
  </div>
  <div class="card-body p-0">
    <ul class="list-group list-group-flush">
      <li id="row-db" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Target Database:</strong>
        <span id="ctx-db" class="badge bg-secondary font-monospace">&mdash;</span>
      </li>
      <li id="row-type" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Context Type:</strong>
        <span id="ctx-type" class="badge bg-light text-dark border font-monospace text-uppercase">&mdash;</span>
      </li>
      <li id="row-severity" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Alert Severity:</strong>
        <span id="ctx-severity" class="badge">&mdash;</span>
      </li>
      <li id="row-time" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Triggered Time:</strong>
        <span id="ctx-time" class="text-muted small">&mdash;</span>
      </li>
      <li id="row-details" class="list-group-item py-2 d-none">
        <strong id="label-details" class="d-block mb-1">Firing Context:</strong>
        <code id="ctx-details" class="d-block p-2 bg-light border rounded small"
          style="white-space: pre-wrap; word-break: break-all;">&mdash;</code>
      </li>
      <li id="row-sql" class="list-group-item py-2 d-none">
        <div class="d-flex justify-content-between align-items-center mb-1">
          <strong id="label-sql">Contextual SQL:</strong>
          <button id="btn-copy-sql" type="button" class="btn btn-sm btn-outline-secondary py-0 px-2 small">
            <i class="bi bi-clipboard me-1"></i>Copy SQL
          </button>
        </div>
        <pre class="mb-0 p-2 bg-light border rounded small"><code id="ctx-sql" style="white-space: pre-wrap; word-break: break-word;">&mdash;</code></pre>
      </li>
    </ul>
  </div>
</div>

<script>
  (function () {
    const params = new URLSearchParams(window.location.search);
    const metadata = params.get('metadata');
    if (!metadata) return;

    try {
      
      const base64 = metadata.replace(/-/g, '+').replace(/_/g, '/');
      const jsonStr = decodeURIComponent(escape(window.atob(base64)));
      const data = JSON.parse(jsonStr);

      if (data) {
        let hasData = false;

        if (data.db) {
          document.getElementById('ctx-db').textContent = data.db;
          document.getElementById('row-db').classList.remove('d-none');
          hasData = true;
        }

        if (data.type) {
          document.getElementById('ctx-type').textContent = data.type;
          document.getElementById('row-type').classList.remove('d-none');
          hasData = true;
        }

        if (data.severity) {
          const severityBadge = document.getElementById('ctx-severity');
          const severity = data.severity.toLowerCase();
          severityBadge.textContent = severity.toUpperCase();
          if (severity === 'critical') {
            severityBadge.className = 'badge bg-danger';
          } else if (severity === 'warning') {
            severityBadge.className = 'badge bg-warning text-dark';
          } else {
            severityBadge.className = 'badge bg-info';
          }
          document.getElementById('row-severity').classList.remove('d-none');
          hasData = true;
        }

        if (data.t) {
          const date = new Date(data.t * 1000);
          document.getElementById('ctx-time').textContent = date.toLocaleString();
          document.getElementById('row-time').classList.remove('d-none');
          hasData = true;
        }

        if (data.details) {
          document.getElementById('ctx-details').textContent = data.details;

          
          const labelDetails = document.getElementById('label-details');
          if (data.type === 'object') {
            labelDetails.textContent = 'Object Metadata Details:';
          } else if (data.type === 'report') {
            labelDetails.textContent = 'Report Description:';
          } else {
            labelDetails.textContent = 'Firing Context:';
          }

          document.getElementById('row-details').classList.remove('d-none');
          hasData = true;
        }

        if (data.sql) {
          document.getElementById('ctx-sql').textContent = data.sql;
          document.getElementById('row-sql').classList.remove('d-none');
          const copyBtn = document.getElementById('btn-copy-sql');
          if (copyBtn && navigator.clipboard) {
            copyBtn.addEventListener('click', function () {
              navigator.clipboard.writeText(data.sql).then(function () {
                copyBtn.innerHTML = '<i class="bi bi-check2 me-1"></i>Copied';
                setTimeout(function () {
                  copyBtn.innerHTML = '<i class="bi bi-clipboard me-1"></i>Copy SQL';
                }, 2000);
              });
            });
          }
          hasData = true;
        }

        if (hasData) {
          document.getElementById('pslens-context-panel').classList.remove('d-none');
        }
      }
    } catch (e) {
      console.error('Failed to parse operational context metadata:', e);
    }
  })();
</script>

## Nodes with No Password Report

**Report ID:** `security-nodes-no-password`
**Category:** Security

## Purpose

This report identifies active PeopleSoft message nodes that have no authentication configured or have authentication enabled but no passwords set. Anything on the network can post messages to these nodes.

## What It Detects

The report categorizes problem nodes into three severity levels:

### CRITICAL — Active Nodes with No Authentication

Active nodes where `AUTHOPTN = 'N'` (None). Any external system can communicate with these nodes without providing any credentials.

### WARNING — Active Nodes with Auth but No Passwords

Active nodes that have an authentication option configured (`AUTHOPTN` is P, C, or T) but neither the internal password (`IBPASSWORD`) nor external password (`IBEXTERNALPWD`) fields contain a value.

### INFO — Inactive Nodes with No Authentication

Nodes that are currently inactive (`ACTIVE_NODE = '0'`) but have no authentication. While not an immediate risk, these would become vulnerable if reactivated.

## Table Queried

### PSMSGNODEDEFN — Message Node Definitions

The primary record for PeopleSoft Integration Broker message nodes.

|     Field     |                 Description                 |                           Values                           |
| ------------- | ------------------------------------------- | ---------------------------------------------------------- |
| MSGNODENAME   | Node name (primary key)                     |                                                            |
| ACTIVE_NODE   | Whether the node is active                  | `1` = Active, `0` = Inactive                               |
| AUTHOPTN      | Authentication option                       | `N` = None, `P` = Password, `C` = Certificate, `T` = Token |
| IBPASSWORD    | Internal password                           | Non-empty means password is set                            |
| IBEXTERNALPWD | External password                           | Non-empty means password is set                            |
| USERID        | PeopleSoft user ID associated with the node |                                                            |
| CONNID        | Connector ID                                | e.g., HTTPTARGET, JMSTARGET                                |
| NODE_TYPE     | Node type                                   |                                                            |
| DESCR         | Description                                 |                                                            |
| LASTUPDOPRID  | Last updated by operator                    |                                                            |
| LASTUPDDTTM   | Last updated timestamp                      |                                                            |

## Data Flow

```text
1. Fetch ALL message nodes from PSMSGNODEDEFN
   via SearchNodes (batches of 300)
        |
        v
2. Categorize each node:
   - Is it active? (ACTIVE_NODE == "1")
   - What is its auth option? (AUTHOPTN)
   - Does it have any password? (IBPASSWORD or IBEXTERNALPWD)
        |
        v
3. Sort into three buckets:
   CRITICAL: Active + AuthOptn == "N"
   WARNING:  Active + AuthOptn != "N" + no passwords
   INFO:     Inactive + AuthOptn == "N"
        |
        v
4. Generate Markdown report grouped by severity
```

## Categorization Logic

The report uses these helper methods on each node record:

|         Method          |                            Logic                            |
| ----------------------- | ----------------------------------------------------------- |
| `IsActive()`            | Returns true if `ACTIVE_NODE == "1"`                        |
| `HasInternalPassword()` | Returns true if `IBPASSWORD` is non-empty                   |
| `HasExternalPassword()` | Returns true if `IBEXTERNALPWD` is non-empty                |
| `HasAnyPassword()`      | Returns true if either internal or external password is set |

## Report Output

The generated report contains:

- **Header** with database name and generation timestamp
- **Summary** with total node counts, active count, and counts per severity category
- **CRITICAL section** (if any): Table with node name, description, node type, connector, user ID, last updated by/when
- **WARNING section** (if any): Table with node name, description, auth option label, internal/external password status (Set/Not Set), user ID, last updated
- **INFO section** (if any): Table with inactive node name, description, node type, last updated by/when
- **Recommendations** based on which severity categories have findings

## Parameters

This report has no configurable parameters.

## Interpreting Results

- **CRITICAL findings require immediate action.** Active nodes with no authentication mean any system on the network can send messages without credentials.
- **WARNING findings should be investigated.** Authentication is configured but credentials may not be properly set, rendering the authentication ineffective.
- **INFO findings are lower priority** but represent latent risk. If these nodes are ever reactivated, they would immediately become vulnerable.

## Authentication Option Reference

| Value |    Label    |           Description            |
| ----- | ----------- | -------------------------------- |
| N     | None        | No authentication required       |
| P     | Password    | Password-based authentication    |
| C     | Certificate | Certificate-based authentication |
| T     | Token       | Token-based authentication       |

## Recommendations and Remediation

### Inbound Nodes: Require Authentication and Lock Down the Default User ID

When a node has `AUTHOPTN = 'N'` (None), any client that can reach the Integration Gateway and specify that node name as the sender (`<RequestingNode>`) can invoke inbound service operations without a password. If the request passes routing checks, Integration Broker executes the subscription or request handler PeopleCode under the security context of the node's **Default User ID** (`PSMSGNODEDEFN.USERID`).

To remediate an active node used for inbound integrations:

1. **Enable Node Authentication**: Navigate to **PeopleTools > Integration Broker > Integration Setup > Node Definitions**, open the node, and change **Authentication Option** from `None` to **Password** (`AUTHOPTN = 'P'`) or **Certificate** (`AUTHOPTN = 'C'`). Note that `Authentication Option = None` is also incompatible with PeopleSoft Single Sign-On (SSO).
2. **Assign a Dedicated, Low-Privilege Default User ID**:
   - Create a unique `OPRID` per integration node following a clear naming convention such as `{ORG_PREFIX}_{APP_NAME}_NODEUSER` (for example, `CHG_SSOSYSTEM_NODE_USER`). This isolates permissions per partner and stamps `LASTUPDOPRID` audit columns with the specific integration identity.
   - **Never assign a superuser account** (such as `PS` or `VP1`) as a node's Default User ID.
   - Do not set a `PSOPRDEFN` login password or grant PIA sign-on / WebLib permissions to this user (inbound node password validation checks the password on the node definition, not `PSOPRDEFN`).
   - Grant the Default User ID permission lists that authorize **only** the specific service operations (`PSAUTHWS`) and Component Interfaces required by that integration partner.
3. **Eliminate `Any-to-Local` (`~~ANY~~`) Routings**: Replace `Any-to-Local` routings on sensitive service operations (such as `USER_PROFILE`) with explicit sender-to-receiver node routings. See the [Active Any-to-Local Routings](/docs/reports/integration-broker/ib-active-any-routes/) and [Unauthenticated Node Service Operations](/docs/reports/integration-broker/ib-noauth-node-svcops/) reports.

### Outbound-Only HTTP Nodes and the `ANONYMOUS` Node

There are two cases where `AUTHOPTN = 'N'` appears intentionally:

- **Outbound-Only External Nodes (`HttpTargetConnector`)**: Node Authentication (`AUTHOPTN`) validates inbound requests from a partner, not outbound requests sent by PeopleSoft. If an External node is used strictly as an outbound HTTP client target, `Authentication Option = None` is only safe if its **Default User ID** is a dummy account with **zero** service operation permissions (`PSAUTHWS`) and no inbound routings accept messages from that node.
- **The Delivered `ANONYMOUS` Node**: PeopleTools uses `ANONYMOUS` as the fallback node when an inbound request omits credentials (used for WSDL/XSD schema retrieval, PeopleSoft Test Framework, and public endpoints). Because `ANONYMOUS` has `AUTHOPTN = 'N'`, its Default User ID must have strictly minimal permissions and must never be paired with sensitive `Any-to-Local` routings.
